protect-mcp 0.5.1 → 0.5.2
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/{chunk-IUFFDQYZ.mjs → chunk-IWDR5WU3.mjs} +1 -1
- package/dist/{chunk-V52W3XIN.mjs → chunk-N4F76LTC.mjs} +12 -8
- package/dist/{chunk-IAJJA5IW.mjs → chunk-Q4KOQUKV.mjs} +1 -1
- package/dist/{chunk-YKM6W6T7.mjs → chunk-W4U5VNEC.mjs} +2 -2
- package/dist/cli.js +12 -8
- package/dist/cli.mjs +4 -4
- package/dist/hook-server.js +12 -8
- package/dist/hook-server.mjs +2 -2
- package/dist/{http-transport-GXIXLVJQ.mjs → http-transport-PWCK7JHZ.mjs} +2 -2
- package/dist/index.d.mts +118 -1
- package/dist/index.d.ts +118 -1
- package/dist/index.js +289 -8
- package/dist/index.mjs +279 -4
- package/package.json +1 -1
|
@@ -232,7 +232,7 @@ function buildEntities(req) {
|
|
|
232
232
|
}
|
|
233
233
|
];
|
|
234
234
|
}
|
|
235
|
-
async function evaluateCedar(policySet, req) {
|
|
235
|
+
async function evaluateCedar(policySet, req, schema) {
|
|
236
236
|
const available = await ensureCedarWasm();
|
|
237
237
|
if (!available) {
|
|
238
238
|
return {
|
|
@@ -243,16 +243,21 @@ async function evaluateCedar(policySet, req) {
|
|
|
243
243
|
}
|
|
244
244
|
try {
|
|
245
245
|
const agentId = req.agentId || req.tier;
|
|
246
|
+
const context = {
|
|
247
|
+
tier: req.tier,
|
|
248
|
+
...req.context || {}
|
|
249
|
+
};
|
|
250
|
+
if (req.toolInput && Object.keys(req.toolInput).length > 0) {
|
|
251
|
+
context.input = req.toolInput;
|
|
252
|
+
}
|
|
246
253
|
const authRequest = {
|
|
247
254
|
principal: { type: "Agent", id: agentId },
|
|
248
255
|
action: { type: "Action", id: "MCP::Tool::call" },
|
|
249
256
|
resource: { type: "Tool", id: req.tool },
|
|
250
|
-
context
|
|
251
|
-
tier: req.tier,
|
|
252
|
-
...req.context || {}
|
|
253
|
-
}
|
|
257
|
+
context
|
|
254
258
|
};
|
|
255
259
|
const entities = buildEntities(req);
|
|
260
|
+
const cedarSchema = schema?.schemaJson ?? null;
|
|
256
261
|
let result;
|
|
257
262
|
if (typeof cedarWasm.isAuthorized === "function") {
|
|
258
263
|
result = cedarWasm.isAuthorized({
|
|
@@ -262,8 +267,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
262
267
|
action: authRequest.action,
|
|
263
268
|
resource: authRequest.resource,
|
|
264
269
|
context: authRequest.context,
|
|
265
|
-
schema:
|
|
266
|
-
// No schema enforcement — Cedar still evaluates correctly
|
|
270
|
+
schema: cedarSchema
|
|
267
271
|
});
|
|
268
272
|
} else if (typeof cedarWasm.checkAuthorization === "function") {
|
|
269
273
|
result = cedarWasm.checkAuthorization(
|
|
@@ -281,7 +285,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
281
285
|
action: authRequest.action,
|
|
282
286
|
resource: authRequest.resource,
|
|
283
287
|
context: authRequest.context,
|
|
284
|
-
schema:
|
|
288
|
+
schema: cedarSchema
|
|
285
289
|
});
|
|
286
290
|
} else {
|
|
287
291
|
return {
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import {
|
|
2
2
|
meetsMinTier
|
|
3
|
-
} from "./chunk-
|
|
3
|
+
} from "./chunk-IWDR5WU3.mjs";
|
|
4
4
|
import {
|
|
5
5
|
checkRateLimit,
|
|
6
6
|
getToolPolicy,
|
|
7
7
|
parseRateLimit
|
|
8
|
-
} from "./chunk-
|
|
8
|
+
} from "./chunk-N4F76LTC.mjs";
|
|
9
9
|
|
|
10
10
|
// src/simulate.ts
|
|
11
11
|
import { readFileSync } from "fs";
|
package/dist/cli.js
CHANGED
|
@@ -682,7 +682,7 @@ function buildEntities(req) {
|
|
|
682
682
|
}
|
|
683
683
|
];
|
|
684
684
|
}
|
|
685
|
-
async function evaluateCedar(policySet, req) {
|
|
685
|
+
async function evaluateCedar(policySet, req, schema) {
|
|
686
686
|
const available = await ensureCedarWasm();
|
|
687
687
|
if (!available) {
|
|
688
688
|
return {
|
|
@@ -693,16 +693,21 @@ async function evaluateCedar(policySet, req) {
|
|
|
693
693
|
}
|
|
694
694
|
try {
|
|
695
695
|
const agentId = req.agentId || req.tier;
|
|
696
|
+
const context = {
|
|
697
|
+
tier: req.tier,
|
|
698
|
+
...req.context || {}
|
|
699
|
+
};
|
|
700
|
+
if (req.toolInput && Object.keys(req.toolInput).length > 0) {
|
|
701
|
+
context.input = req.toolInput;
|
|
702
|
+
}
|
|
696
703
|
const authRequest = {
|
|
697
704
|
principal: { type: "Agent", id: agentId },
|
|
698
705
|
action: { type: "Action", id: "MCP::Tool::call" },
|
|
699
706
|
resource: { type: "Tool", id: req.tool },
|
|
700
|
-
context
|
|
701
|
-
tier: req.tier,
|
|
702
|
-
...req.context || {}
|
|
703
|
-
}
|
|
707
|
+
context
|
|
704
708
|
};
|
|
705
709
|
const entities = buildEntities(req);
|
|
710
|
+
const cedarSchema = schema?.schemaJson ?? null;
|
|
706
711
|
let result;
|
|
707
712
|
if (typeof cedarWasm.isAuthorized === "function") {
|
|
708
713
|
result = cedarWasm.isAuthorized({
|
|
@@ -712,8 +717,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
712
717
|
action: authRequest.action,
|
|
713
718
|
resource: authRequest.resource,
|
|
714
719
|
context: authRequest.context,
|
|
715
|
-
schema:
|
|
716
|
-
// No schema enforcement — Cedar still evaluates correctly
|
|
720
|
+
schema: cedarSchema
|
|
717
721
|
});
|
|
718
722
|
} else if (typeof cedarWasm.checkAuthorization === "function") {
|
|
719
723
|
result = cedarWasm.checkAuthorization(
|
|
@@ -731,7 +735,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
731
735
|
action: authRequest.action,
|
|
732
736
|
resource: authRequest.resource,
|
|
733
737
|
context: authRequest.context,
|
|
734
|
-
schema:
|
|
738
|
+
schema: cedarSchema
|
|
735
739
|
});
|
|
736
740
|
} else {
|
|
737
741
|
return {
|
package/dist/cli.mjs
CHANGED
|
@@ -3,17 +3,17 @@ import {
|
|
|
3
3
|
formatSimulation,
|
|
4
4
|
parseLogFile,
|
|
5
5
|
simulate
|
|
6
|
-
} from "./chunk-
|
|
6
|
+
} from "./chunk-W4U5VNEC.mjs";
|
|
7
7
|
import {
|
|
8
8
|
ProtectGateway,
|
|
9
9
|
validateCredentials
|
|
10
|
-
} from "./chunk-
|
|
10
|
+
} from "./chunk-IWDR5WU3.mjs";
|
|
11
11
|
import {
|
|
12
12
|
initSigning,
|
|
13
13
|
isCedarAvailable,
|
|
14
14
|
loadCedarPolicies,
|
|
15
15
|
loadPolicy
|
|
16
|
-
} from "./chunk-
|
|
16
|
+
} from "./chunk-N4F76LTC.mjs";
|
|
17
17
|
import "./chunk-PQJP2ZCI.mjs";
|
|
18
18
|
|
|
19
19
|
// src/cli.ts
|
|
@@ -1282,7 +1282,7 @@ async function main() {
|
|
|
1282
1282
|
if (useHttp) {
|
|
1283
1283
|
const portIdx = args.indexOf("--port");
|
|
1284
1284
|
const httpPort = portIdx >= 0 && args[portIdx + 1] ? parseInt(args[portIdx + 1]) : 3e3;
|
|
1285
|
-
const { startHttpTransport } = await import("./http-transport-
|
|
1285
|
+
const { startHttpTransport } = await import("./http-transport-PWCK7JHZ.mjs");
|
|
1286
1286
|
startHttpTransport({ port: httpPort, config, serverCommand: childCommand });
|
|
1287
1287
|
return;
|
|
1288
1288
|
}
|
package/dist/hook-server.js
CHANGED
|
@@ -89,7 +89,7 @@ function buildEntities(req) {
|
|
|
89
89
|
}
|
|
90
90
|
];
|
|
91
91
|
}
|
|
92
|
-
async function evaluateCedar(policySet, req) {
|
|
92
|
+
async function evaluateCedar(policySet, req, schema) {
|
|
93
93
|
const available = await ensureCedarWasm();
|
|
94
94
|
if (!available) {
|
|
95
95
|
return {
|
|
@@ -100,16 +100,21 @@ async function evaluateCedar(policySet, req) {
|
|
|
100
100
|
}
|
|
101
101
|
try {
|
|
102
102
|
const agentId = req.agentId || req.tier;
|
|
103
|
+
const context = {
|
|
104
|
+
tier: req.tier,
|
|
105
|
+
...req.context || {}
|
|
106
|
+
};
|
|
107
|
+
if (req.toolInput && Object.keys(req.toolInput).length > 0) {
|
|
108
|
+
context.input = req.toolInput;
|
|
109
|
+
}
|
|
103
110
|
const authRequest = {
|
|
104
111
|
principal: { type: "Agent", id: agentId },
|
|
105
112
|
action: { type: "Action", id: "MCP::Tool::call" },
|
|
106
113
|
resource: { type: "Tool", id: req.tool },
|
|
107
|
-
context
|
|
108
|
-
tier: req.tier,
|
|
109
|
-
...req.context || {}
|
|
110
|
-
}
|
|
114
|
+
context
|
|
111
115
|
};
|
|
112
116
|
const entities = buildEntities(req);
|
|
117
|
+
const cedarSchema = schema?.schemaJson ?? null;
|
|
113
118
|
let result;
|
|
114
119
|
if (typeof cedarWasm.isAuthorized === "function") {
|
|
115
120
|
result = cedarWasm.isAuthorized({
|
|
@@ -119,8 +124,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
119
124
|
action: authRequest.action,
|
|
120
125
|
resource: authRequest.resource,
|
|
121
126
|
context: authRequest.context,
|
|
122
|
-
schema:
|
|
123
|
-
// No schema enforcement — Cedar still evaluates correctly
|
|
127
|
+
schema: cedarSchema
|
|
124
128
|
});
|
|
125
129
|
} else if (typeof cedarWasm.checkAuthorization === "function") {
|
|
126
130
|
result = cedarWasm.checkAuthorization(
|
|
@@ -138,7 +142,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
138
142
|
action: authRequest.action,
|
|
139
143
|
resource: authRequest.resource,
|
|
140
144
|
context: authRequest.context,
|
|
141
|
-
schema:
|
|
145
|
+
schema: cedarSchema
|
|
142
146
|
});
|
|
143
147
|
} else {
|
|
144
148
|
return {
|
package/dist/hook-server.mjs
CHANGED
package/dist/index.d.mts
CHANGED
|
@@ -539,6 +539,45 @@ interface CedarPolicySet {
|
|
|
539
539
|
/** Filenames loaded */
|
|
540
540
|
files: string[];
|
|
541
541
|
}
|
|
542
|
+
interface CedarEvalRequest {
|
|
543
|
+
/** Tool name being called */
|
|
544
|
+
tool: string;
|
|
545
|
+
/** Trust tier of the agent */
|
|
546
|
+
tier: TrustTier;
|
|
547
|
+
/** Agent ID (optional) */
|
|
548
|
+
agentId?: string;
|
|
549
|
+
/** Additional context fields */
|
|
550
|
+
context?: Record<string, unknown>;
|
|
551
|
+
/** Tool input (for schema-validated evaluation) */
|
|
552
|
+
toolInput?: Record<string, unknown>;
|
|
553
|
+
}
|
|
554
|
+
/** Cedar schema for typed policy evaluation (generated by cedar-schema.ts) */
|
|
555
|
+
interface CedarSchema {
|
|
556
|
+
/** The schema as a JSON object for Cedar WASM */
|
|
557
|
+
schemaJson: Record<string, unknown> | null;
|
|
558
|
+
/** Namespace used in the schema */
|
|
559
|
+
namespace?: string;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Load all .cedar files from a directory and return a compiled policy set.
|
|
563
|
+
*
|
|
564
|
+
* Files are sorted alphabetically for deterministic digest computation.
|
|
565
|
+
* Throws if the directory doesn't exist or contains no .cedar files.
|
|
566
|
+
*/
|
|
567
|
+
declare function loadCedarPolicies(dirPath: string): CedarPolicySet;
|
|
568
|
+
/**
|
|
569
|
+
* Evaluate a Cedar policy set against a tool call.
|
|
570
|
+
*
|
|
571
|
+
* Returns a standard ExternalDecision compatible with the gateway's
|
|
572
|
+
* decision pipeline. If Cedar WASM is not available, returns a
|
|
573
|
+
* fallback allow decision (fail-open, logged).
|
|
574
|
+
*/
|
|
575
|
+
declare function evaluateCedar(policySet: CedarPolicySet, req: CedarEvalRequest, schema?: CedarSchema): Promise<ExternalDecision>;
|
|
576
|
+
/**
|
|
577
|
+
* Validate that Cedar WASM is available.
|
|
578
|
+
* Useful for CLI startup diagnostics.
|
|
579
|
+
*/
|
|
580
|
+
declare function isCedarAvailable(): Promise<boolean>;
|
|
542
581
|
|
|
543
582
|
/**
|
|
544
583
|
* MCP tool-calling gateway that intercepts JSON-RPC requests,
|
|
@@ -1313,6 +1352,84 @@ declare function validateManifest(manifest: unknown): string[];
|
|
|
1313
1352
|
*/
|
|
1314
1353
|
declare function validateEvidenceReceipt(receipt: unknown): string[];
|
|
1315
1354
|
|
|
1355
|
+
/**
|
|
1356
|
+
* @scopeblind/protect-mcp — Cedar Schema Generator for MCP Tools
|
|
1357
|
+
*
|
|
1358
|
+
* Auto-generates a Cedar authorization schema from MCP tool descriptions.
|
|
1359
|
+
* This enables typed Cedar policies that reference tool input attributes:
|
|
1360
|
+
*
|
|
1361
|
+
* permit(principal, action == Action::"read_file", resource)
|
|
1362
|
+
* when { context.input.path like "./workspace/*" };
|
|
1363
|
+
*
|
|
1364
|
+
* Compatible with cedar-policy/cedar-for-agents schema format.
|
|
1365
|
+
* Designed to replace `schema: null` in Cedar WASM evaluations.
|
|
1366
|
+
*
|
|
1367
|
+
* @see https://github.com/cedar-policy/cedar-for-agents
|
|
1368
|
+
* @standard RFC 8785 (JCS), Cedar Policy Language v4
|
|
1369
|
+
*/
|
|
1370
|
+
/** MCP tool description from tools/list response */
|
|
1371
|
+
interface McpToolDescription {
|
|
1372
|
+
name: string;
|
|
1373
|
+
description?: string;
|
|
1374
|
+
inputSchema?: JsonSchema;
|
|
1375
|
+
}
|
|
1376
|
+
/** Subset of JSON Schema that MCP tools use */
|
|
1377
|
+
interface JsonSchema {
|
|
1378
|
+
type?: string | string[];
|
|
1379
|
+
properties?: Record<string, JsonSchema>;
|
|
1380
|
+
required?: string[];
|
|
1381
|
+
items?: JsonSchema;
|
|
1382
|
+
enum?: (string | number | boolean)[];
|
|
1383
|
+
format?: string;
|
|
1384
|
+
description?: string;
|
|
1385
|
+
additionalProperties?: boolean | JsonSchema;
|
|
1386
|
+
anyOf?: JsonSchema[];
|
|
1387
|
+
oneOf?: JsonSchema[];
|
|
1388
|
+
}
|
|
1389
|
+
/** Generated Cedar schema components */
|
|
1390
|
+
interface CedarSchemaResult {
|
|
1391
|
+
/** The .cedarschema text (human-readable Cedar schema format) */
|
|
1392
|
+
schemaText: string;
|
|
1393
|
+
/** The schema as a JSON object (for passing to Cedar WASM) */
|
|
1394
|
+
schemaJson: Record<string, unknown>;
|
|
1395
|
+
/** Number of tools mapped */
|
|
1396
|
+
toolCount: number;
|
|
1397
|
+
/** Tool names included */
|
|
1398
|
+
tools: string[];
|
|
1399
|
+
}
|
|
1400
|
+
interface SchemaGeneratorConfig {
|
|
1401
|
+
/** Namespace for generated types (default: "ScopeBlind") */
|
|
1402
|
+
namespace?: string;
|
|
1403
|
+
/** Include agent tier as principal attribute (default: true) */
|
|
1404
|
+
includeTier?: boolean;
|
|
1405
|
+
/** Include timestamp context (default: true) */
|
|
1406
|
+
includeTimestamp?: boolean;
|
|
1407
|
+
/** Include agent_id as principal attribute (default: true) */
|
|
1408
|
+
includeAgentId?: boolean;
|
|
1409
|
+
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Generate a Cedar schema from MCP tool descriptions.
|
|
1412
|
+
*
|
|
1413
|
+
* Produces both human-readable .cedarschema text and the JSON
|
|
1414
|
+
* representation that Cedar WASM accepts.
|
|
1415
|
+
*
|
|
1416
|
+
* The generated schema defines:
|
|
1417
|
+
* - Agent entity type (principal) with tier and agent_id attributes
|
|
1418
|
+
* - Tool entity type (resource)
|
|
1419
|
+
* - One action per MCP tool, with typed input context
|
|
1420
|
+
* - A parent action "MCP::Tool::call" for blanket policies
|
|
1421
|
+
*
|
|
1422
|
+
* This enables policies like:
|
|
1423
|
+
* forbid(principal, action == Action::"execute_command", resource)
|
|
1424
|
+
* when { context.input has "command" && context.input.command like "rm *" };
|
|
1425
|
+
*/
|
|
1426
|
+
declare function generateCedarSchema(tools: McpToolDescription[], config?: SchemaGeneratorConfig): CedarSchemaResult;
|
|
1427
|
+
/**
|
|
1428
|
+
* Generate a Cedar schema stub file for customization.
|
|
1429
|
+
* This is the starting point for users who want to extend the auto-generated schema.
|
|
1430
|
+
*/
|
|
1431
|
+
declare function generateSchemaStub(namespace?: string): string;
|
|
1432
|
+
|
|
1316
1433
|
/**
|
|
1317
1434
|
* Sigstore Rekor Transparency Log Anchoring
|
|
1318
1435
|
*
|
|
@@ -2639,4 +2756,4 @@ declare function confidentialInference(_prompt: string, _config: ConfidentialInf
|
|
|
2639
2756
|
receipt: Record<string, unknown>;
|
|
2640
2757
|
}>;
|
|
2641
2758
|
|
|
2642
|
-
export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, ed25519ToDIDKey, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, generateC2PACommand, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runInSandbox, sendApprovalNotification, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };
|
|
2759
|
+
export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type CedarEvalRequest, type CedarPolicySet, type CedarSchema, type CedarSchemaResult, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type McpToolDescription, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SchemaGeneratorConfig, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, ed25519ToDIDKey, evaluateCedar, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, generateC2PACommand, generateCedarSchema, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, generateSchemaStub, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isCedarAvailable, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadCedarPolicies, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runInSandbox, sendApprovalNotification, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };
|
package/dist/index.d.ts
CHANGED
|
@@ -539,6 +539,45 @@ interface CedarPolicySet {
|
|
|
539
539
|
/** Filenames loaded */
|
|
540
540
|
files: string[];
|
|
541
541
|
}
|
|
542
|
+
interface CedarEvalRequest {
|
|
543
|
+
/** Tool name being called */
|
|
544
|
+
tool: string;
|
|
545
|
+
/** Trust tier of the agent */
|
|
546
|
+
tier: TrustTier;
|
|
547
|
+
/** Agent ID (optional) */
|
|
548
|
+
agentId?: string;
|
|
549
|
+
/** Additional context fields */
|
|
550
|
+
context?: Record<string, unknown>;
|
|
551
|
+
/** Tool input (for schema-validated evaluation) */
|
|
552
|
+
toolInput?: Record<string, unknown>;
|
|
553
|
+
}
|
|
554
|
+
/** Cedar schema for typed policy evaluation (generated by cedar-schema.ts) */
|
|
555
|
+
interface CedarSchema {
|
|
556
|
+
/** The schema as a JSON object for Cedar WASM */
|
|
557
|
+
schemaJson: Record<string, unknown> | null;
|
|
558
|
+
/** Namespace used in the schema */
|
|
559
|
+
namespace?: string;
|
|
560
|
+
}
|
|
561
|
+
/**
|
|
562
|
+
* Load all .cedar files from a directory and return a compiled policy set.
|
|
563
|
+
*
|
|
564
|
+
* Files are sorted alphabetically for deterministic digest computation.
|
|
565
|
+
* Throws if the directory doesn't exist or contains no .cedar files.
|
|
566
|
+
*/
|
|
567
|
+
declare function loadCedarPolicies(dirPath: string): CedarPolicySet;
|
|
568
|
+
/**
|
|
569
|
+
* Evaluate a Cedar policy set against a tool call.
|
|
570
|
+
*
|
|
571
|
+
* Returns a standard ExternalDecision compatible with the gateway's
|
|
572
|
+
* decision pipeline. If Cedar WASM is not available, returns a
|
|
573
|
+
* fallback allow decision (fail-open, logged).
|
|
574
|
+
*/
|
|
575
|
+
declare function evaluateCedar(policySet: CedarPolicySet, req: CedarEvalRequest, schema?: CedarSchema): Promise<ExternalDecision>;
|
|
576
|
+
/**
|
|
577
|
+
* Validate that Cedar WASM is available.
|
|
578
|
+
* Useful for CLI startup diagnostics.
|
|
579
|
+
*/
|
|
580
|
+
declare function isCedarAvailable(): Promise<boolean>;
|
|
542
581
|
|
|
543
582
|
/**
|
|
544
583
|
* MCP tool-calling gateway that intercepts JSON-RPC requests,
|
|
@@ -1313,6 +1352,84 @@ declare function validateManifest(manifest: unknown): string[];
|
|
|
1313
1352
|
*/
|
|
1314
1353
|
declare function validateEvidenceReceipt(receipt: unknown): string[];
|
|
1315
1354
|
|
|
1355
|
+
/**
|
|
1356
|
+
* @scopeblind/protect-mcp — Cedar Schema Generator for MCP Tools
|
|
1357
|
+
*
|
|
1358
|
+
* Auto-generates a Cedar authorization schema from MCP tool descriptions.
|
|
1359
|
+
* This enables typed Cedar policies that reference tool input attributes:
|
|
1360
|
+
*
|
|
1361
|
+
* permit(principal, action == Action::"read_file", resource)
|
|
1362
|
+
* when { context.input.path like "./workspace/*" };
|
|
1363
|
+
*
|
|
1364
|
+
* Compatible with cedar-policy/cedar-for-agents schema format.
|
|
1365
|
+
* Designed to replace `schema: null` in Cedar WASM evaluations.
|
|
1366
|
+
*
|
|
1367
|
+
* @see https://github.com/cedar-policy/cedar-for-agents
|
|
1368
|
+
* @standard RFC 8785 (JCS), Cedar Policy Language v4
|
|
1369
|
+
*/
|
|
1370
|
+
/** MCP tool description from tools/list response */
|
|
1371
|
+
interface McpToolDescription {
|
|
1372
|
+
name: string;
|
|
1373
|
+
description?: string;
|
|
1374
|
+
inputSchema?: JsonSchema;
|
|
1375
|
+
}
|
|
1376
|
+
/** Subset of JSON Schema that MCP tools use */
|
|
1377
|
+
interface JsonSchema {
|
|
1378
|
+
type?: string | string[];
|
|
1379
|
+
properties?: Record<string, JsonSchema>;
|
|
1380
|
+
required?: string[];
|
|
1381
|
+
items?: JsonSchema;
|
|
1382
|
+
enum?: (string | number | boolean)[];
|
|
1383
|
+
format?: string;
|
|
1384
|
+
description?: string;
|
|
1385
|
+
additionalProperties?: boolean | JsonSchema;
|
|
1386
|
+
anyOf?: JsonSchema[];
|
|
1387
|
+
oneOf?: JsonSchema[];
|
|
1388
|
+
}
|
|
1389
|
+
/** Generated Cedar schema components */
|
|
1390
|
+
interface CedarSchemaResult {
|
|
1391
|
+
/** The .cedarschema text (human-readable Cedar schema format) */
|
|
1392
|
+
schemaText: string;
|
|
1393
|
+
/** The schema as a JSON object (for passing to Cedar WASM) */
|
|
1394
|
+
schemaJson: Record<string, unknown>;
|
|
1395
|
+
/** Number of tools mapped */
|
|
1396
|
+
toolCount: number;
|
|
1397
|
+
/** Tool names included */
|
|
1398
|
+
tools: string[];
|
|
1399
|
+
}
|
|
1400
|
+
interface SchemaGeneratorConfig {
|
|
1401
|
+
/** Namespace for generated types (default: "ScopeBlind") */
|
|
1402
|
+
namespace?: string;
|
|
1403
|
+
/** Include agent tier as principal attribute (default: true) */
|
|
1404
|
+
includeTier?: boolean;
|
|
1405
|
+
/** Include timestamp context (default: true) */
|
|
1406
|
+
includeTimestamp?: boolean;
|
|
1407
|
+
/** Include agent_id as principal attribute (default: true) */
|
|
1408
|
+
includeAgentId?: boolean;
|
|
1409
|
+
}
|
|
1410
|
+
/**
|
|
1411
|
+
* Generate a Cedar schema from MCP tool descriptions.
|
|
1412
|
+
*
|
|
1413
|
+
* Produces both human-readable .cedarschema text and the JSON
|
|
1414
|
+
* representation that Cedar WASM accepts.
|
|
1415
|
+
*
|
|
1416
|
+
* The generated schema defines:
|
|
1417
|
+
* - Agent entity type (principal) with tier and agent_id attributes
|
|
1418
|
+
* - Tool entity type (resource)
|
|
1419
|
+
* - One action per MCP tool, with typed input context
|
|
1420
|
+
* - A parent action "MCP::Tool::call" for blanket policies
|
|
1421
|
+
*
|
|
1422
|
+
* This enables policies like:
|
|
1423
|
+
* forbid(principal, action == Action::"execute_command", resource)
|
|
1424
|
+
* when { context.input has "command" && context.input.command like "rm *" };
|
|
1425
|
+
*/
|
|
1426
|
+
declare function generateCedarSchema(tools: McpToolDescription[], config?: SchemaGeneratorConfig): CedarSchemaResult;
|
|
1427
|
+
/**
|
|
1428
|
+
* Generate a Cedar schema stub file for customization.
|
|
1429
|
+
* This is the starting point for users who want to extend the auto-generated schema.
|
|
1430
|
+
*/
|
|
1431
|
+
declare function generateSchemaStub(namespace?: string): string;
|
|
1432
|
+
|
|
1316
1433
|
/**
|
|
1317
1434
|
* Sigstore Rekor Transparency Log Anchoring
|
|
1318
1435
|
*
|
|
@@ -2639,4 +2756,4 @@ declare function confidentialInference(_prompt: string, _config: ConfidentialInf
|
|
|
2639
2756
|
receipt: Record<string, unknown>;
|
|
2640
2757
|
}>;
|
|
2641
2758
|
|
|
2642
|
-
export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, ed25519ToDIDKey, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, generateC2PACommand, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runInSandbox, sendApprovalNotification, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };
|
|
2759
|
+
export { type ActionReceipt, type AdmissionResult, type AgentId, type AgentManifest, type ApprovalAssertion, type ApprovalChallenge, type ApprovalNotification, type ApprovalResult, type ArenaPayload, type ArenaReceipt, type AttestationDocument, type AttestationPayload, type AttestationProvider, type AttestationReceipt, type AttestationResult, type AuditBundle, type AuditBundleOptions, type BenchmarkPayload, type BenchmarkReceipt, type BuilderId, type C2PAAssertion, type C2PAIngredient, type C2PAManifest, type C2PAOptions, type CCRConnectorConfig, type CCRSessionContext, type CalibrationScore, type CedarEvalRequest, type CedarPolicySet, type CedarSchema, type CedarSchemaResult, type ComplianceReport, ConfidentialGate, type ConfidentialGateConfig, type ConfidentialInferenceConfig, type CredentialConfig, type DecisionContext, type DecisionLog, type DelegationReceipt, type DisclosureMode, type Ed25519PublicKey, type EvidenceAttestation, type EvidenceAttestationInput, type EvidenceIssuer, type EvidenceReceipt, type EvidenceReceiptBase, type EvidenceSummary, type EvidenceSummaryEntry, type EvidenceType, type ExternalDecision, type ExternalPDPConfig, type HFDatasetMetadata, type HFReceiptRow, type HookEventName, type HookInput, type HookResponse, type IssuerType, type JsonRpcRequest, type JsonRpcResponse, type LeaseCompatibility, type ManifestBuilder, type ManifestCapabilities, type ManifestConfig, type ManifestIdentity, type ManifestPresentation, type ManifestSignature, type ManifestStatus, type McpToolDescription, type NotificationConfig, type PassportTokenClaims, type PayloadDigest, type PlanReceipt, type PolicyEngineMode, type PredictionReceipt, type PredictionResolution, type PropagatorConfig, type ProtectConfig, ProtectGateway, type ProtectPolicy, type RateLimit, ReceiptPropagator, type RedactedResult, type RedactionSalt, type RekorAnchor, type RekorVerification, type RestraintPayload, type RestraintReceipt, type SHA256Hash, type SafetyTranscript, type Sandbox, type SandboxConfig, type SandboxReceipt, type SandboxResult, type SandboxToolCall, type SchemaGeneratorConfig, type SigningConfig, type SimulationResult, type SimulationSummary, type SwarmContext, type TierOverrides, type TimingMetrics, type ToolPolicy, type TrustTier, type WorkPayload, type WorkReceipt, anchorToRekor, buildDecisionContext, checkRateLimit, collectSignedReceipts, computeCalibration, confidentialInference, createApprovalChallenge, createApprovalReceiptPayload, createAttestationField, createAuditBundle, createC2PAManifest, createDisclosurePackage, createEvidenceAttestation, createLogAnchorField, createReceiptChannel, createSandbox, destroySandbox, ed25519ToDIDKey, evaluateCedar, evaluateTier, exportC2PAManifestJSON, exportJSONL, formatReportMarkdown, formatSimulation, generateC2PACommand, generateCedarSchema, generateDatasetCard, generateHFMetadata, generateReport, generateSafetyTranscript, generateSchemaStub, getSignerInfo, getToolPolicy, hashReceipt, hashResponseBody, initSigning, isAgentId, isCedarAvailable, isDisclosureMode, isEvidenceType, isManifestStatus, isSigningEnabled, listCredentialLabels, loadCedarPolicies, loadPolicy, manifestToVC, meetsMinTier, parseLogFile, parseNotificationConfigFromEnv, parseRateLimit, queryExternalPDP, receiptToVP, receiptsToHFRows, redactFields, resolveCredential, revealField, runInSandbox, sendApprovalNotification, signDecision, simulate, toCredentialRequestOptions, toManifoldFormat, toMetaculusFormat, validateCredentials, validateEvidenceReceipt, validateManifest, verifyActaC2PAAssertions, verifyAllCommitments, verifyApprovalAssertion, verifyCommitment, verifyEvidenceAttestation, verifyRekorAnchor };
|
package/dist/index.js
CHANGED
|
@@ -35041,18 +35041,21 @@ __export(index_exports, {
|
|
|
35041
35041
|
createSandboxServer: () => createSandboxServer,
|
|
35042
35042
|
destroySandbox: () => destroySandbox,
|
|
35043
35043
|
ed25519ToDIDKey: () => ed25519ToDIDKey,
|
|
35044
|
+
evaluateCedar: () => evaluateCedar,
|
|
35044
35045
|
evaluateTier: () => evaluateTier,
|
|
35045
35046
|
exportC2PAManifestJSON: () => exportC2PAManifestJSON,
|
|
35046
35047
|
exportJSONL: () => exportJSONL,
|
|
35047
35048
|
formatReportMarkdown: () => formatReportMarkdown,
|
|
35048
35049
|
formatSimulation: () => formatSimulation,
|
|
35049
35050
|
generateC2PACommand: () => generateC2PACommand,
|
|
35051
|
+
generateCedarSchema: () => generateCedarSchema,
|
|
35050
35052
|
generateDatasetCard: () => generateDatasetCard,
|
|
35051
35053
|
generateHFMetadata: () => generateHFMetadata,
|
|
35052
35054
|
generateHookSettings: () => generateHookSettings,
|
|
35053
35055
|
generateReport: () => generateReport,
|
|
35054
35056
|
generateSafetyTranscript: () => generateSafetyTranscript,
|
|
35055
35057
|
generateSampleCedarPolicy: () => generateSampleCedarPolicy,
|
|
35058
|
+
generateSchemaStub: () => generateSchemaStub,
|
|
35056
35059
|
generateVerifyReceiptSkill: () => generateVerifyReceiptSkill,
|
|
35057
35060
|
getSignerInfo: () => getSignerInfo,
|
|
35058
35061
|
getToolPolicy: () => getToolPolicy,
|
|
@@ -35060,11 +35063,13 @@ __export(index_exports, {
|
|
|
35060
35063
|
hashResponseBody: () => hashResponseBody,
|
|
35061
35064
|
initSigning: () => initSigning,
|
|
35062
35065
|
isAgentId: () => isAgentId,
|
|
35066
|
+
isCedarAvailable: () => isCedarAvailable,
|
|
35063
35067
|
isDisclosureMode: () => isDisclosureMode,
|
|
35064
35068
|
isEvidenceType: () => isEvidenceType,
|
|
35065
35069
|
isManifestStatus: () => isManifestStatus,
|
|
35066
35070
|
isSigningEnabled: () => isSigningEnabled,
|
|
35067
35071
|
listCredentialLabels: () => listCredentialLabels,
|
|
35072
|
+
loadCedarPolicies: () => loadCedarPolicies,
|
|
35068
35073
|
loadPolicy: () => loadPolicy,
|
|
35069
35074
|
manifestToVC: () => manifestToVC,
|
|
35070
35075
|
meetsMinTier: () => meetsMinTier,
|
|
@@ -35731,7 +35736,7 @@ function buildEntities(req) {
|
|
|
35731
35736
|
}
|
|
35732
35737
|
];
|
|
35733
35738
|
}
|
|
35734
|
-
async function evaluateCedar(policySet, req) {
|
|
35739
|
+
async function evaluateCedar(policySet, req, schema) {
|
|
35735
35740
|
const available = await ensureCedarWasm();
|
|
35736
35741
|
if (!available) {
|
|
35737
35742
|
return {
|
|
@@ -35742,16 +35747,21 @@ async function evaluateCedar(policySet, req) {
|
|
|
35742
35747
|
}
|
|
35743
35748
|
try {
|
|
35744
35749
|
const agentId = req.agentId || req.tier;
|
|
35750
|
+
const context = {
|
|
35751
|
+
tier: req.tier,
|
|
35752
|
+
...req.context || {}
|
|
35753
|
+
};
|
|
35754
|
+
if (req.toolInput && Object.keys(req.toolInput).length > 0) {
|
|
35755
|
+
context.input = req.toolInput;
|
|
35756
|
+
}
|
|
35745
35757
|
const authRequest = {
|
|
35746
35758
|
principal: { type: "Agent", id: agentId },
|
|
35747
35759
|
action: { type: "Action", id: "MCP::Tool::call" },
|
|
35748
35760
|
resource: { type: "Tool", id: req.tool },
|
|
35749
|
-
context
|
|
35750
|
-
tier: req.tier,
|
|
35751
|
-
...req.context || {}
|
|
35752
|
-
}
|
|
35761
|
+
context
|
|
35753
35762
|
};
|
|
35754
35763
|
const entities = buildEntities(req);
|
|
35764
|
+
const cedarSchema = schema?.schemaJson ?? null;
|
|
35755
35765
|
let result;
|
|
35756
35766
|
if (typeof cedarWasm.isAuthorized === "function") {
|
|
35757
35767
|
result = cedarWasm.isAuthorized({
|
|
@@ -35761,8 +35771,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
35761
35771
|
action: authRequest.action,
|
|
35762
35772
|
resource: authRequest.resource,
|
|
35763
35773
|
context: authRequest.context,
|
|
35764
|
-
schema:
|
|
35765
|
-
// No schema enforcement — Cedar still evaluates correctly
|
|
35774
|
+
schema: cedarSchema
|
|
35766
35775
|
});
|
|
35767
35776
|
} else if (typeof cedarWasm.checkAuthorization === "function") {
|
|
35768
35777
|
result = cedarWasm.checkAuthorization(
|
|
@@ -35780,7 +35789,7 @@ async function evaluateCedar(policySet, req) {
|
|
|
35780
35789
|
action: authRequest.action,
|
|
35781
35790
|
resource: authRequest.resource,
|
|
35782
35791
|
context: authRequest.context,
|
|
35783
|
-
schema:
|
|
35792
|
+
schema: cedarSchema
|
|
35784
35793
|
});
|
|
35785
35794
|
} else {
|
|
35786
35795
|
return {
|
|
@@ -38381,6 +38390,273 @@ If swarm data exists, show the agent topology (coordinator \u2192 workers).
|
|
|
38381
38390
|
`;
|
|
38382
38391
|
}
|
|
38383
38392
|
|
|
38393
|
+
// src/cedar-schema.ts
|
|
38394
|
+
function jsonSchemaToCedarType(schema, namespace, path) {
|
|
38395
|
+
if (schema.enum) {
|
|
38396
|
+
return "String";
|
|
38397
|
+
}
|
|
38398
|
+
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
38399
|
+
switch (type) {
|
|
38400
|
+
case "string":
|
|
38401
|
+
if (schema.format === "date-time") return "String";
|
|
38402
|
+
if (schema.format === "uri") return "String";
|
|
38403
|
+
return "String";
|
|
38404
|
+
case "integer":
|
|
38405
|
+
case "number":
|
|
38406
|
+
return "Long";
|
|
38407
|
+
case "boolean":
|
|
38408
|
+
return "Bool";
|
|
38409
|
+
case "array":
|
|
38410
|
+
if (schema.items) {
|
|
38411
|
+
const itemType = jsonSchemaToCedarType(schema.items, namespace, path + "_item");
|
|
38412
|
+
return `Set<${itemType}>`;
|
|
38413
|
+
}
|
|
38414
|
+
return "Set<String>";
|
|
38415
|
+
// Default to Set<String> for untyped arrays
|
|
38416
|
+
case "object":
|
|
38417
|
+
if (schema.properties && Object.keys(schema.properties).length > 0) {
|
|
38418
|
+
const fields = Object.entries(schema.properties).map(([key, prop]) => {
|
|
38419
|
+
const cedarType = jsonSchemaToCedarType(prop, namespace, path + "_" + sanitizeIdentifier(key));
|
|
38420
|
+
const isRequired = schema.required?.includes(key) ?? false;
|
|
38421
|
+
return ` "${sanitizeIdentifier(key)}": ${cedarType}${isRequired ? "" : "?"}`;
|
|
38422
|
+
});
|
|
38423
|
+
return `{
|
|
38424
|
+
${fields.join(",\n")}
|
|
38425
|
+
}`;
|
|
38426
|
+
}
|
|
38427
|
+
return "Record";
|
|
38428
|
+
// Empty objects
|
|
38429
|
+
default:
|
|
38430
|
+
return "String";
|
|
38431
|
+
}
|
|
38432
|
+
}
|
|
38433
|
+
function sanitizeIdentifier(name) {
|
|
38434
|
+
return name.replace(/[^a-zA-Z0-9_]/g, "_").replace(/^(\d)/, "_$1");
|
|
38435
|
+
}
|
|
38436
|
+
function cedarActionId(toolName) {
|
|
38437
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(toolName)) {
|
|
38438
|
+
return toolName;
|
|
38439
|
+
}
|
|
38440
|
+
return toolName;
|
|
38441
|
+
}
|
|
38442
|
+
function generateCedarSchema(tools, config = {}) {
|
|
38443
|
+
const ns = config.namespace || "ScopeBlind";
|
|
38444
|
+
const includeTier = config.includeTier !== false;
|
|
38445
|
+
const includeTimestamp = config.includeTimestamp !== false;
|
|
38446
|
+
const includeAgentId = config.includeAgentId !== false;
|
|
38447
|
+
const agentAttrs = [];
|
|
38448
|
+
if (includeTier) agentAttrs.push(' "tier": String');
|
|
38449
|
+
if (includeAgentId) agentAttrs.push(' "agent_id": String?');
|
|
38450
|
+
const sessionFields = [];
|
|
38451
|
+
if (includeTimestamp) sessionFields.push(' "timestamp": String?');
|
|
38452
|
+
sessionFields.push(' "hook_event": String?');
|
|
38453
|
+
const actionDeclarations = [];
|
|
38454
|
+
const inputTypeDeclarations = [];
|
|
38455
|
+
for (const tool of tools) {
|
|
38456
|
+
const actionName = cedarActionId(tool.name);
|
|
38457
|
+
const inputTypeName = `${sanitizeIdentifier(tool.name)}_Input`;
|
|
38458
|
+
if (tool.inputSchema?.properties && Object.keys(tool.inputSchema.properties).length > 0) {
|
|
38459
|
+
const fields = Object.entries(tool.inputSchema.properties).map(([key, prop]) => {
|
|
38460
|
+
const cedarType = jsonSchemaToCedarType(prop, ns, sanitizeIdentifier(tool.name) + "_" + sanitizeIdentifier(key));
|
|
38461
|
+
const isRequired = tool.inputSchema?.required?.includes(key) ?? false;
|
|
38462
|
+
return ` "${sanitizeIdentifier(key)}": ${cedarType}${isRequired ? "" : "?"}`;
|
|
38463
|
+
});
|
|
38464
|
+
inputTypeDeclarations.push(
|
|
38465
|
+
` // Input type for tool: ${tool.name}` + (tool.description ? `
|
|
38466
|
+
// ${tool.description}` : "") + `
|
|
38467
|
+
type ${inputTypeName} = {
|
|
38468
|
+
${fields.join(",\n")}
|
|
38469
|
+
};`
|
|
38470
|
+
);
|
|
38471
|
+
actionDeclarations.push(
|
|
38472
|
+
` action "${actionName}" in [Action::"MCP::Tool::call"] appliesTo {
|
|
38473
|
+
principal: [Agent],
|
|
38474
|
+
resource: [Tool],
|
|
38475
|
+
context: {
|
|
38476
|
+
"input": ${inputTypeName},
|
|
38477
|
+
"tier": String${includeTimestamp ? ',\n "timestamp": String?' : ""}${includeAgentId ? ',\n "agent_id": String?' : ""}
|
|
38478
|
+
}
|
|
38479
|
+
};`
|
|
38480
|
+
);
|
|
38481
|
+
} else {
|
|
38482
|
+
actionDeclarations.push(
|
|
38483
|
+
` action "${actionName}" in [Action::"MCP::Tool::call"] appliesTo {
|
|
38484
|
+
principal: [Agent],
|
|
38485
|
+
resource: [Tool],
|
|
38486
|
+
context: {
|
|
38487
|
+
"tier": String${includeTimestamp ? ',\n "timestamp": String?' : ""}${includeAgentId ? ',\n "agent_id": String?' : ""}
|
|
38488
|
+
}
|
|
38489
|
+
};`
|
|
38490
|
+
);
|
|
38491
|
+
}
|
|
38492
|
+
}
|
|
38493
|
+
actionDeclarations.push(
|
|
38494
|
+
` // Blanket action for policies matching any tool call
|
|
38495
|
+
action "MCP::Tool::call" appliesTo {
|
|
38496
|
+
principal: [Agent],
|
|
38497
|
+
resource: [Tool],
|
|
38498
|
+
context: {
|
|
38499
|
+
"tier": String${includeTimestamp ? ',\n "timestamp": String?' : ""}${includeAgentId ? ',\n "agent_id": String?' : ""}
|
|
38500
|
+
}
|
|
38501
|
+
};`
|
|
38502
|
+
);
|
|
38503
|
+
const schemaText = [
|
|
38504
|
+
`// Cedar schema for MCP tool governance`,
|
|
38505
|
+
`// Generated by protect-mcp from ${tools.length} tool description(s)`,
|
|
38506
|
+
`// Compatible with cedar-policy/cedar-for-agents`,
|
|
38507
|
+
``,
|
|
38508
|
+
`namespace ${ns} {`,
|
|
38509
|
+
``,
|
|
38510
|
+
` // \u2500\u2500 Entity types \u2500\u2500`,
|
|
38511
|
+
``,
|
|
38512
|
+
` entity Agent${agentAttrs.length > 0 ? ` = {
|
|
38513
|
+
${agentAttrs.join(",\n")}
|
|
38514
|
+
}` : ""};`,
|
|
38515
|
+
``,
|
|
38516
|
+
` entity Tool;`,
|
|
38517
|
+
``,
|
|
38518
|
+
...inputTypeDeclarations.length > 0 ? [` // \u2500\u2500 Tool input types \u2500\u2500`, ``, ...inputTypeDeclarations, ``] : [],
|
|
38519
|
+
` // \u2500\u2500 Actions \u2500\u2500`,
|
|
38520
|
+
``,
|
|
38521
|
+
...actionDeclarations,
|
|
38522
|
+
``,
|
|
38523
|
+
`}`,
|
|
38524
|
+
``
|
|
38525
|
+
].join("\n");
|
|
38526
|
+
const schemaJson = buildSchemaJson(tools, ns, config);
|
|
38527
|
+
return {
|
|
38528
|
+
schemaText,
|
|
38529
|
+
schemaJson,
|
|
38530
|
+
toolCount: tools.length,
|
|
38531
|
+
tools: tools.map((t) => t.name)
|
|
38532
|
+
};
|
|
38533
|
+
}
|
|
38534
|
+
function buildSchemaJson(tools, namespace, config) {
|
|
38535
|
+
const entityTypes = {
|
|
38536
|
+
Agent: {
|
|
38537
|
+
shape: {
|
|
38538
|
+
type: "Record",
|
|
38539
|
+
attributes: {
|
|
38540
|
+
...config.includeTier !== false ? { tier: { type: "String", required: false } } : {},
|
|
38541
|
+
...config.includeAgentId !== false ? { agent_id: { type: "String", required: false } } : {}
|
|
38542
|
+
}
|
|
38543
|
+
},
|
|
38544
|
+
memberOfTypes: []
|
|
38545
|
+
},
|
|
38546
|
+
Tool: {
|
|
38547
|
+
shape: { type: "Record", attributes: {} },
|
|
38548
|
+
memberOfTypes: []
|
|
38549
|
+
}
|
|
38550
|
+
};
|
|
38551
|
+
const actions = {};
|
|
38552
|
+
for (const tool of tools) {
|
|
38553
|
+
const contextAttrs = {
|
|
38554
|
+
tier: { type: "String", required: false }
|
|
38555
|
+
};
|
|
38556
|
+
if (config.includeTimestamp !== false) {
|
|
38557
|
+
contextAttrs["timestamp"] = { type: "String", required: false };
|
|
38558
|
+
}
|
|
38559
|
+
if (config.includeAgentId !== false) {
|
|
38560
|
+
contextAttrs["agent_id"] = { type: "String", required: false };
|
|
38561
|
+
}
|
|
38562
|
+
if (tool.inputSchema?.properties) {
|
|
38563
|
+
const inputAttrs = {};
|
|
38564
|
+
for (const [key, prop] of Object.entries(tool.inputSchema.properties)) {
|
|
38565
|
+
inputAttrs[sanitizeIdentifier(key)] = {
|
|
38566
|
+
type: jsonSchemaToSchemaJsonType(prop),
|
|
38567
|
+
required: tool.inputSchema.required?.includes(key) ?? false
|
|
38568
|
+
};
|
|
38569
|
+
}
|
|
38570
|
+
contextAttrs["input"] = {
|
|
38571
|
+
type: "Record",
|
|
38572
|
+
attributes: inputAttrs,
|
|
38573
|
+
required: false
|
|
38574
|
+
};
|
|
38575
|
+
}
|
|
38576
|
+
actions[tool.name] = {
|
|
38577
|
+
appliesTo: {
|
|
38578
|
+
principalTypes: ["Agent"],
|
|
38579
|
+
resourceTypes: ["Tool"],
|
|
38580
|
+
context: { type: "Record", attributes: contextAttrs }
|
|
38581
|
+
},
|
|
38582
|
+
memberOf: [{ id: "MCP::Tool::call" }]
|
|
38583
|
+
};
|
|
38584
|
+
}
|
|
38585
|
+
const blanketContext = {
|
|
38586
|
+
tier: { type: "String", required: false }
|
|
38587
|
+
};
|
|
38588
|
+
if (config.includeTimestamp !== false) {
|
|
38589
|
+
blanketContext["timestamp"] = { type: "String", required: false };
|
|
38590
|
+
}
|
|
38591
|
+
if (config.includeAgentId !== false) {
|
|
38592
|
+
blanketContext["agent_id"] = { type: "String", required: false };
|
|
38593
|
+
}
|
|
38594
|
+
actions["MCP::Tool::call"] = {
|
|
38595
|
+
appliesTo: {
|
|
38596
|
+
principalTypes: ["Agent"],
|
|
38597
|
+
resourceTypes: ["Tool"],
|
|
38598
|
+
context: { type: "Record", attributes: blanketContext }
|
|
38599
|
+
}
|
|
38600
|
+
};
|
|
38601
|
+
return {
|
|
38602
|
+
[namespace]: {
|
|
38603
|
+
entityTypes,
|
|
38604
|
+
actions
|
|
38605
|
+
}
|
|
38606
|
+
};
|
|
38607
|
+
}
|
|
38608
|
+
function jsonSchemaToSchemaJsonType(schema) {
|
|
38609
|
+
if (schema.enum) return "String";
|
|
38610
|
+
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
38611
|
+
switch (type) {
|
|
38612
|
+
case "string":
|
|
38613
|
+
return "String";
|
|
38614
|
+
case "integer":
|
|
38615
|
+
case "number":
|
|
38616
|
+
return "Long";
|
|
38617
|
+
case "boolean":
|
|
38618
|
+
return "EntityOrCommon";
|
|
38619
|
+
// Cedar JSON schema uses this for Bool
|
|
38620
|
+
case "array":
|
|
38621
|
+
return "Set";
|
|
38622
|
+
default:
|
|
38623
|
+
return "String";
|
|
38624
|
+
}
|
|
38625
|
+
}
|
|
38626
|
+
function generateSchemaStub(namespace = "ScopeBlind") {
|
|
38627
|
+
return [
|
|
38628
|
+
`// Cedar schema stub for protect-mcp`,
|
|
38629
|
+
`// This defines the principal and resource entity types.`,
|
|
38630
|
+
`// Tool-specific actions are auto-generated from MCP tools/list.`,
|
|
38631
|
+
`//`,
|
|
38632
|
+
`// Compatible with cedar-policy/cedar-for-agents @mcp_principal/@mcp_resource annotations.`,
|
|
38633
|
+
`// See: https://github.com/cedar-policy/cedar-for-agents`,
|
|
38634
|
+
``,
|
|
38635
|
+
`namespace ${namespace} {`,
|
|
38636
|
+
``,
|
|
38637
|
+
` // @mcp_principal`,
|
|
38638
|
+
` entity Agent = {`,
|
|
38639
|
+
` "tier": String,`,
|
|
38640
|
+
` "agent_id": String?`,
|
|
38641
|
+
` };`,
|
|
38642
|
+
``,
|
|
38643
|
+
` // @mcp_resource`,
|
|
38644
|
+
` entity Tool;`,
|
|
38645
|
+
``,
|
|
38646
|
+
` // @mcp_action`,
|
|
38647
|
+
` action "MCP::Tool::call" appliesTo {`,
|
|
38648
|
+
` principal: [Agent],`,
|
|
38649
|
+
` resource: [Tool],`,
|
|
38650
|
+
` context: {`,
|
|
38651
|
+
` "tier": String`,
|
|
38652
|
+
` }`,
|
|
38653
|
+
` };`,
|
|
38654
|
+
``,
|
|
38655
|
+
`}`,
|
|
38656
|
+
``
|
|
38657
|
+
].join("\n");
|
|
38658
|
+
}
|
|
38659
|
+
|
|
38384
38660
|
// src/rekor-anchor.ts
|
|
38385
38661
|
var import_node_crypto5 = require("crypto");
|
|
38386
38662
|
var REKOR_API = "https://rekor.sigstore.dev/api/v1";
|
|
@@ -39807,18 +40083,21 @@ function createSandboxServer() {
|
|
|
39807
40083
|
createSandboxServer,
|
|
39808
40084
|
destroySandbox,
|
|
39809
40085
|
ed25519ToDIDKey,
|
|
40086
|
+
evaluateCedar,
|
|
39810
40087
|
evaluateTier,
|
|
39811
40088
|
exportC2PAManifestJSON,
|
|
39812
40089
|
exportJSONL,
|
|
39813
40090
|
formatReportMarkdown,
|
|
39814
40091
|
formatSimulation,
|
|
39815
40092
|
generateC2PACommand,
|
|
40093
|
+
generateCedarSchema,
|
|
39816
40094
|
generateDatasetCard,
|
|
39817
40095
|
generateHFMetadata,
|
|
39818
40096
|
generateHookSettings,
|
|
39819
40097
|
generateReport,
|
|
39820
40098
|
generateSafetyTranscript,
|
|
39821
40099
|
generateSampleCedarPolicy,
|
|
40100
|
+
generateSchemaStub,
|
|
39822
40101
|
generateVerifyReceiptSkill,
|
|
39823
40102
|
getSignerInfo,
|
|
39824
40103
|
getToolPolicy,
|
|
@@ -39826,11 +40105,13 @@ function createSandboxServer() {
|
|
|
39826
40105
|
hashResponseBody,
|
|
39827
40106
|
initSigning,
|
|
39828
40107
|
isAgentId,
|
|
40108
|
+
isCedarAvailable,
|
|
39829
40109
|
isDisclosureMode,
|
|
39830
40110
|
isEvidenceType,
|
|
39831
40111
|
isManifestStatus,
|
|
39832
40112
|
isSigningEnabled,
|
|
39833
40113
|
listCredentialLabels,
|
|
40114
|
+
loadCedarPolicies,
|
|
39834
40115
|
loadPolicy,
|
|
39835
40116
|
manifestToVC,
|
|
39836
40117
|
meetsMinTier,
|
package/dist/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
formatSimulation,
|
|
7
7
|
parseLogFile,
|
|
8
8
|
simulate
|
|
9
|
-
} from "./chunk-
|
|
9
|
+
} from "./chunk-W4U5VNEC.mjs";
|
|
10
10
|
import {
|
|
11
11
|
ProtectGateway,
|
|
12
12
|
buildDecisionContext,
|
|
@@ -18,7 +18,7 @@ import {
|
|
|
18
18
|
resolveCredential,
|
|
19
19
|
sendApprovalNotification,
|
|
20
20
|
validateCredentials
|
|
21
|
-
} from "./chunk-
|
|
21
|
+
} from "./chunk-IWDR5WU3.mjs";
|
|
22
22
|
import {
|
|
23
23
|
createSandboxServer
|
|
24
24
|
} from "./chunk-SU2FZH7U.mjs";
|
|
@@ -30,17 +30,20 @@ import {
|
|
|
30
30
|
} from "./chunk-UEHLYOJY.mjs";
|
|
31
31
|
import {
|
|
32
32
|
startHookServer
|
|
33
|
-
} from "./chunk-
|
|
33
|
+
} from "./chunk-Q4KOQUKV.mjs";
|
|
34
34
|
import {
|
|
35
35
|
checkRateLimit,
|
|
36
|
+
evaluateCedar,
|
|
36
37
|
getSignerInfo,
|
|
37
38
|
getToolPolicy,
|
|
38
39
|
initSigning,
|
|
40
|
+
isCedarAvailable,
|
|
39
41
|
isSigningEnabled,
|
|
42
|
+
loadCedarPolicies,
|
|
40
43
|
loadPolicy,
|
|
41
44
|
parseRateLimit,
|
|
42
45
|
signDecision
|
|
43
|
-
} from "./chunk-
|
|
46
|
+
} from "./chunk-N4F76LTC.mjs";
|
|
44
47
|
import {
|
|
45
48
|
collectSignedReceipts,
|
|
46
49
|
createAuditBundle
|
|
@@ -202,6 +205,273 @@ function validateEvidenceReceipt(receipt) {
|
|
|
202
205
|
return errors;
|
|
203
206
|
}
|
|
204
207
|
|
|
208
|
+
// src/cedar-schema.ts
|
|
209
|
+
function jsonSchemaToCedarType(schema, namespace, path) {
|
|
210
|
+
if (schema.enum) {
|
|
211
|
+
return "String";
|
|
212
|
+
}
|
|
213
|
+
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
214
|
+
switch (type) {
|
|
215
|
+
case "string":
|
|
216
|
+
if (schema.format === "date-time") return "String";
|
|
217
|
+
if (schema.format === "uri") return "String";
|
|
218
|
+
return "String";
|
|
219
|
+
case "integer":
|
|
220
|
+
case "number":
|
|
221
|
+
return "Long";
|
|
222
|
+
case "boolean":
|
|
223
|
+
return "Bool";
|
|
224
|
+
case "array":
|
|
225
|
+
if (schema.items) {
|
|
226
|
+
const itemType = jsonSchemaToCedarType(schema.items, namespace, path + "_item");
|
|
227
|
+
return `Set<${itemType}>`;
|
|
228
|
+
}
|
|
229
|
+
return "Set<String>";
|
|
230
|
+
// Default to Set<String> for untyped arrays
|
|
231
|
+
case "object":
|
|
232
|
+
if (schema.properties && Object.keys(schema.properties).length > 0) {
|
|
233
|
+
const fields = Object.entries(schema.properties).map(([key, prop]) => {
|
|
234
|
+
const cedarType = jsonSchemaToCedarType(prop, namespace, path + "_" + sanitizeIdentifier(key));
|
|
235
|
+
const isRequired = schema.required?.includes(key) ?? false;
|
|
236
|
+
return ` "${sanitizeIdentifier(key)}": ${cedarType}${isRequired ? "" : "?"}`;
|
|
237
|
+
});
|
|
238
|
+
return `{
|
|
239
|
+
${fields.join(",\n")}
|
|
240
|
+
}`;
|
|
241
|
+
}
|
|
242
|
+
return "Record";
|
|
243
|
+
// Empty objects
|
|
244
|
+
default:
|
|
245
|
+
return "String";
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
function sanitizeIdentifier(name) {
|
|
249
|
+
return name.replace(/[^a-zA-Z0-9_]/g, "_").replace(/^(\d)/, "_$1");
|
|
250
|
+
}
|
|
251
|
+
function cedarActionId(toolName) {
|
|
252
|
+
if (/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(toolName)) {
|
|
253
|
+
return toolName;
|
|
254
|
+
}
|
|
255
|
+
return toolName;
|
|
256
|
+
}
|
|
257
|
+
function generateCedarSchema(tools, config = {}) {
|
|
258
|
+
const ns = config.namespace || "ScopeBlind";
|
|
259
|
+
const includeTier = config.includeTier !== false;
|
|
260
|
+
const includeTimestamp = config.includeTimestamp !== false;
|
|
261
|
+
const includeAgentId = config.includeAgentId !== false;
|
|
262
|
+
const agentAttrs = [];
|
|
263
|
+
if (includeTier) agentAttrs.push(' "tier": String');
|
|
264
|
+
if (includeAgentId) agentAttrs.push(' "agent_id": String?');
|
|
265
|
+
const sessionFields = [];
|
|
266
|
+
if (includeTimestamp) sessionFields.push(' "timestamp": String?');
|
|
267
|
+
sessionFields.push(' "hook_event": String?');
|
|
268
|
+
const actionDeclarations = [];
|
|
269
|
+
const inputTypeDeclarations = [];
|
|
270
|
+
for (const tool of tools) {
|
|
271
|
+
const actionName = cedarActionId(tool.name);
|
|
272
|
+
const inputTypeName = `${sanitizeIdentifier(tool.name)}_Input`;
|
|
273
|
+
if (tool.inputSchema?.properties && Object.keys(tool.inputSchema.properties).length > 0) {
|
|
274
|
+
const fields = Object.entries(tool.inputSchema.properties).map(([key, prop]) => {
|
|
275
|
+
const cedarType = jsonSchemaToCedarType(prop, ns, sanitizeIdentifier(tool.name) + "_" + sanitizeIdentifier(key));
|
|
276
|
+
const isRequired = tool.inputSchema?.required?.includes(key) ?? false;
|
|
277
|
+
return ` "${sanitizeIdentifier(key)}": ${cedarType}${isRequired ? "" : "?"}`;
|
|
278
|
+
});
|
|
279
|
+
inputTypeDeclarations.push(
|
|
280
|
+
` // Input type for tool: ${tool.name}` + (tool.description ? `
|
|
281
|
+
// ${tool.description}` : "") + `
|
|
282
|
+
type ${inputTypeName} = {
|
|
283
|
+
${fields.join(",\n")}
|
|
284
|
+
};`
|
|
285
|
+
);
|
|
286
|
+
actionDeclarations.push(
|
|
287
|
+
` action "${actionName}" in [Action::"MCP::Tool::call"] appliesTo {
|
|
288
|
+
principal: [Agent],
|
|
289
|
+
resource: [Tool],
|
|
290
|
+
context: {
|
|
291
|
+
"input": ${inputTypeName},
|
|
292
|
+
"tier": String${includeTimestamp ? ',\n "timestamp": String?' : ""}${includeAgentId ? ',\n "agent_id": String?' : ""}
|
|
293
|
+
}
|
|
294
|
+
};`
|
|
295
|
+
);
|
|
296
|
+
} else {
|
|
297
|
+
actionDeclarations.push(
|
|
298
|
+
` action "${actionName}" in [Action::"MCP::Tool::call"] appliesTo {
|
|
299
|
+
principal: [Agent],
|
|
300
|
+
resource: [Tool],
|
|
301
|
+
context: {
|
|
302
|
+
"tier": String${includeTimestamp ? ',\n "timestamp": String?' : ""}${includeAgentId ? ',\n "agent_id": String?' : ""}
|
|
303
|
+
}
|
|
304
|
+
};`
|
|
305
|
+
);
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
actionDeclarations.push(
|
|
309
|
+
` // Blanket action for policies matching any tool call
|
|
310
|
+
action "MCP::Tool::call" appliesTo {
|
|
311
|
+
principal: [Agent],
|
|
312
|
+
resource: [Tool],
|
|
313
|
+
context: {
|
|
314
|
+
"tier": String${includeTimestamp ? ',\n "timestamp": String?' : ""}${includeAgentId ? ',\n "agent_id": String?' : ""}
|
|
315
|
+
}
|
|
316
|
+
};`
|
|
317
|
+
);
|
|
318
|
+
const schemaText = [
|
|
319
|
+
`// Cedar schema for MCP tool governance`,
|
|
320
|
+
`// Generated by protect-mcp from ${tools.length} tool description(s)`,
|
|
321
|
+
`// Compatible with cedar-policy/cedar-for-agents`,
|
|
322
|
+
``,
|
|
323
|
+
`namespace ${ns} {`,
|
|
324
|
+
``,
|
|
325
|
+
` // \u2500\u2500 Entity types \u2500\u2500`,
|
|
326
|
+
``,
|
|
327
|
+
` entity Agent${agentAttrs.length > 0 ? ` = {
|
|
328
|
+
${agentAttrs.join(",\n")}
|
|
329
|
+
}` : ""};`,
|
|
330
|
+
``,
|
|
331
|
+
` entity Tool;`,
|
|
332
|
+
``,
|
|
333
|
+
...inputTypeDeclarations.length > 0 ? [` // \u2500\u2500 Tool input types \u2500\u2500`, ``, ...inputTypeDeclarations, ``] : [],
|
|
334
|
+
` // \u2500\u2500 Actions \u2500\u2500`,
|
|
335
|
+
``,
|
|
336
|
+
...actionDeclarations,
|
|
337
|
+
``,
|
|
338
|
+
`}`,
|
|
339
|
+
``
|
|
340
|
+
].join("\n");
|
|
341
|
+
const schemaJson = buildSchemaJson(tools, ns, config);
|
|
342
|
+
return {
|
|
343
|
+
schemaText,
|
|
344
|
+
schemaJson,
|
|
345
|
+
toolCount: tools.length,
|
|
346
|
+
tools: tools.map((t) => t.name)
|
|
347
|
+
};
|
|
348
|
+
}
|
|
349
|
+
function buildSchemaJson(tools, namespace, config) {
|
|
350
|
+
const entityTypes = {
|
|
351
|
+
Agent: {
|
|
352
|
+
shape: {
|
|
353
|
+
type: "Record",
|
|
354
|
+
attributes: {
|
|
355
|
+
...config.includeTier !== false ? { tier: { type: "String", required: false } } : {},
|
|
356
|
+
...config.includeAgentId !== false ? { agent_id: { type: "String", required: false } } : {}
|
|
357
|
+
}
|
|
358
|
+
},
|
|
359
|
+
memberOfTypes: []
|
|
360
|
+
},
|
|
361
|
+
Tool: {
|
|
362
|
+
shape: { type: "Record", attributes: {} },
|
|
363
|
+
memberOfTypes: []
|
|
364
|
+
}
|
|
365
|
+
};
|
|
366
|
+
const actions = {};
|
|
367
|
+
for (const tool of tools) {
|
|
368
|
+
const contextAttrs = {
|
|
369
|
+
tier: { type: "String", required: false }
|
|
370
|
+
};
|
|
371
|
+
if (config.includeTimestamp !== false) {
|
|
372
|
+
contextAttrs["timestamp"] = { type: "String", required: false };
|
|
373
|
+
}
|
|
374
|
+
if (config.includeAgentId !== false) {
|
|
375
|
+
contextAttrs["agent_id"] = { type: "String", required: false };
|
|
376
|
+
}
|
|
377
|
+
if (tool.inputSchema?.properties) {
|
|
378
|
+
const inputAttrs = {};
|
|
379
|
+
for (const [key, prop] of Object.entries(tool.inputSchema.properties)) {
|
|
380
|
+
inputAttrs[sanitizeIdentifier(key)] = {
|
|
381
|
+
type: jsonSchemaToSchemaJsonType(prop),
|
|
382
|
+
required: tool.inputSchema.required?.includes(key) ?? false
|
|
383
|
+
};
|
|
384
|
+
}
|
|
385
|
+
contextAttrs["input"] = {
|
|
386
|
+
type: "Record",
|
|
387
|
+
attributes: inputAttrs,
|
|
388
|
+
required: false
|
|
389
|
+
};
|
|
390
|
+
}
|
|
391
|
+
actions[tool.name] = {
|
|
392
|
+
appliesTo: {
|
|
393
|
+
principalTypes: ["Agent"],
|
|
394
|
+
resourceTypes: ["Tool"],
|
|
395
|
+
context: { type: "Record", attributes: contextAttrs }
|
|
396
|
+
},
|
|
397
|
+
memberOf: [{ id: "MCP::Tool::call" }]
|
|
398
|
+
};
|
|
399
|
+
}
|
|
400
|
+
const blanketContext = {
|
|
401
|
+
tier: { type: "String", required: false }
|
|
402
|
+
};
|
|
403
|
+
if (config.includeTimestamp !== false) {
|
|
404
|
+
blanketContext["timestamp"] = { type: "String", required: false };
|
|
405
|
+
}
|
|
406
|
+
if (config.includeAgentId !== false) {
|
|
407
|
+
blanketContext["agent_id"] = { type: "String", required: false };
|
|
408
|
+
}
|
|
409
|
+
actions["MCP::Tool::call"] = {
|
|
410
|
+
appliesTo: {
|
|
411
|
+
principalTypes: ["Agent"],
|
|
412
|
+
resourceTypes: ["Tool"],
|
|
413
|
+
context: { type: "Record", attributes: blanketContext }
|
|
414
|
+
}
|
|
415
|
+
};
|
|
416
|
+
return {
|
|
417
|
+
[namespace]: {
|
|
418
|
+
entityTypes,
|
|
419
|
+
actions
|
|
420
|
+
}
|
|
421
|
+
};
|
|
422
|
+
}
|
|
423
|
+
function jsonSchemaToSchemaJsonType(schema) {
|
|
424
|
+
if (schema.enum) return "String";
|
|
425
|
+
const type = Array.isArray(schema.type) ? schema.type[0] : schema.type;
|
|
426
|
+
switch (type) {
|
|
427
|
+
case "string":
|
|
428
|
+
return "String";
|
|
429
|
+
case "integer":
|
|
430
|
+
case "number":
|
|
431
|
+
return "Long";
|
|
432
|
+
case "boolean":
|
|
433
|
+
return "EntityOrCommon";
|
|
434
|
+
// Cedar JSON schema uses this for Bool
|
|
435
|
+
case "array":
|
|
436
|
+
return "Set";
|
|
437
|
+
default:
|
|
438
|
+
return "String";
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
function generateSchemaStub(namespace = "ScopeBlind") {
|
|
442
|
+
return [
|
|
443
|
+
`// Cedar schema stub for protect-mcp`,
|
|
444
|
+
`// This defines the principal and resource entity types.`,
|
|
445
|
+
`// Tool-specific actions are auto-generated from MCP tools/list.`,
|
|
446
|
+
`//`,
|
|
447
|
+
`// Compatible with cedar-policy/cedar-for-agents @mcp_principal/@mcp_resource annotations.`,
|
|
448
|
+
`// See: https://github.com/cedar-policy/cedar-for-agents`,
|
|
449
|
+
``,
|
|
450
|
+
`namespace ${namespace} {`,
|
|
451
|
+
``,
|
|
452
|
+
` // @mcp_principal`,
|
|
453
|
+
` entity Agent = {`,
|
|
454
|
+
` "tier": String,`,
|
|
455
|
+
` "agent_id": String?`,
|
|
456
|
+
` };`,
|
|
457
|
+
``,
|
|
458
|
+
` // @mcp_resource`,
|
|
459
|
+
` entity Tool;`,
|
|
460
|
+
``,
|
|
461
|
+
` // @mcp_action`,
|
|
462
|
+
` action "MCP::Tool::call" appliesTo {`,
|
|
463
|
+
` principal: [Agent],`,
|
|
464
|
+
` resource: [Tool],`,
|
|
465
|
+
` context: {`,
|
|
466
|
+
` "tier": String`,
|
|
467
|
+
` }`,
|
|
468
|
+
` };`,
|
|
469
|
+
``,
|
|
470
|
+
`}`,
|
|
471
|
+
``
|
|
472
|
+
].join("\n");
|
|
473
|
+
}
|
|
474
|
+
|
|
205
475
|
// src/rekor-anchor.ts
|
|
206
476
|
import { createHash } from "crypto";
|
|
207
477
|
var REKOR_API = "https://rekor.sigstore.dev/api/v1";
|
|
@@ -1452,18 +1722,21 @@ export {
|
|
|
1452
1722
|
createSandboxServer,
|
|
1453
1723
|
destroySandbox,
|
|
1454
1724
|
ed25519ToDIDKey,
|
|
1725
|
+
evaluateCedar,
|
|
1455
1726
|
evaluateTier,
|
|
1456
1727
|
exportC2PAManifestJSON,
|
|
1457
1728
|
exportJSONL,
|
|
1458
1729
|
formatReportMarkdown,
|
|
1459
1730
|
formatSimulation,
|
|
1460
1731
|
generateC2PACommand,
|
|
1732
|
+
generateCedarSchema,
|
|
1461
1733
|
generateDatasetCard,
|
|
1462
1734
|
generateHFMetadata,
|
|
1463
1735
|
generateHookSettings,
|
|
1464
1736
|
generateReport,
|
|
1465
1737
|
generateSafetyTranscript,
|
|
1466
1738
|
generateSampleCedarPolicy,
|
|
1739
|
+
generateSchemaStub,
|
|
1467
1740
|
generateVerifyReceiptSkill,
|
|
1468
1741
|
getSignerInfo,
|
|
1469
1742
|
getToolPolicy,
|
|
@@ -1471,11 +1744,13 @@ export {
|
|
|
1471
1744
|
hashResponseBody,
|
|
1472
1745
|
initSigning,
|
|
1473
1746
|
isAgentId,
|
|
1747
|
+
isCedarAvailable,
|
|
1474
1748
|
isDisclosureMode,
|
|
1475
1749
|
isEvidenceType,
|
|
1476
1750
|
isManifestStatus,
|
|
1477
1751
|
isSigningEnabled,
|
|
1478
1752
|
listCredentialLabels,
|
|
1753
|
+
loadCedarPolicies,
|
|
1479
1754
|
loadPolicy,
|
|
1480
1755
|
manifestToVC,
|
|
1481
1756
|
meetsMinTier,
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "protect-mcp",
|
|
3
|
-
"version": "0.5.
|
|
3
|
+
"version": "0.5.2",
|
|
4
4
|
"mcpName": "io.github.tomjwxf/protect-mcp",
|
|
5
5
|
"description": "Enterprise security gateway for MCP servers and Claude Code hooks. Cedar policies, Ed25519-signed receipts, swarm tracking, and tamper detection. Shadow or enforce mode.",
|
|
6
6
|
"main": "dist/index.js",
|