protect-mcp 0.5.0 → 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/README.md +152 -161
- 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 +6 -3
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,
|