@receiz/mcp-server
Version:
MCP server for agents building and verifying Receiz proof-native applications through the canonical Receiz SDK rails.
173 lines • 9.48 kB
JavaScript
import { isReceizV125TrustMcpHost, assertReceizV125TrustMcpHostScope } from "./v125TrustHost.js";
const object = (properties, required = []) => ({
type: "object", additionalProperties: false, properties, required,
});
const text = (description) => ({ type: "string", description });
export const RECEIZ_V125_TRUST_MCP_TOOL_NAMES = Object.freeze([
"receiz_v125_attestation_domain_resolve",
"receiz_v125_attestation_application_plan",
"receiz_v125_attestation_application_apply",
"receiz_v125_attestation_workflow_plan",
"receiz_v125_attestation_workflow_apply",
"receiz_v125_attestation_evidence_plan",
"receiz_v125_attestation_evidence_apply",
"receiz_v125_attestation_evaluation_plan",
"receiz_v125_attestation_evaluation_apply",
"receiz_v125_attestation_review_plan",
"receiz_v125_attestation_review_apply",
"receiz_v125_attestation_approval_plan",
"receiz_v125_attestation_approval_apply",
"receiz_v125_credential_issue_plan",
"receiz_v125_credential_issue_apply",
"receiz_v125_credential_lifecycle_plan",
"receiz_v125_credential_lifecycle_apply",
"receiz_v125_credential_currentness_resolve",
"receiz_v125_pbi_ceremony_challenge_create",
"receiz_v125_pbi_ceremony_approve",
"receiz_v125_pbi_ceremony_receipt_issue",
"receiz_v125_pbi_ceremony_receipt_verify",
"receiz_v125_pbi_ceremony_challenge_redeem",
"receiz_v125_credential_presentation_create",
"receiz_v125_credential_presentation_verify",
"receiz_v125_credential_presentation_handoff_resolve",
"receiz_v125_subject_relationship_plan",
"receiz_v125_subject_relationship_apply",
"receiz_v125_subject_introduction_plan",
"receiz_v125_subject_introduction_apply",
"receiz_v125_subject_message_plan",
"receiz_v125_subject_message_apply",
"receiz_v125_subject_presence_plan",
"receiz_v125_subject_presence_apply",
"receiz_v125_subject_discovery_resolve",
"receiz_v125_external_execution_plan",
"receiz_v125_external_execution_execute",
"receiz_v125_external_execution_resolve",
"receiz_v125_external_execution_verify",
]);
const READ_ONLY_SUFFIXES = ["_resolve", "_verify"];
const isReadOnly = (name) => READ_ONLY_SUFFIXES.some((suffix) => name.endsWith(suffix));
export const RECEIZ_V125_TRUST_MCP_REQUIRED_SCOPES = Object.freeze(Object.fromEntries(RECEIZ_V125_TRUST_MCP_TOOL_NAMES.map((name) => [
name,
Object.freeze([isReadOnly(name) ? "receiz:proof.read" : "receiz:proof.write"]),
])));
function inputSchema(name) {
const properties = {
proofReference: text("Opaque trusted-host proof Reference; sealed bytes and private claims never enter model context."),
selectedKai: text("Optional exact KKS uPulse selected for currentness or expiry evaluation."),
};
if (!isReadOnly(name)) {
properties.idempotencyKey = text("Stable semantic retry identity bound by the trusted host.");
properties.confirmationDigest = text("Exact preview confirmation digest required before trusted-host execution.");
}
return object(properties, ["proofReference", ...(!isReadOnly(name) ? ["idempotencyKey"] : [])]);
}
const projectionAuthority = Object.freeze({ mcpIsProofAuthority: false, strongerTruth: "sealed-receiz-proof-object" });
const RESULT_REFERENCE_FIELDS = ["planReference", "proofReference", "resultReference", "sourceFamilyReference"];
const RESULT_DIGEST_FIELDS = ["confirmationDigest", "acceptedHead"];
const RESULT_TOKEN_FIELDS = ["status", "code", "missingBoundary"];
const RESULT_FIELDS = new Set([
...RESULT_REFERENCE_FIELDS, ...RESULT_DIGEST_FIELDS, ...RESULT_TOKEN_FIELDS,
"writesPerformed", "confirmationRequired", "authority",
]);
const resultSchema = object({
...Object.fromEntries(RESULT_REFERENCE_FIELDS.map((key) => [key, { type: "string", minLength: 1, maxLength: 512 }])),
...Object.fromEntries(RESULT_DIGEST_FIELDS.map((key) => [key, { type: "string", pattern: "^[0-9a-f]{64}$" }])),
...Object.fromEntries(RESULT_TOKEN_FIELDS.map((key) => [key, { type: "string", pattern: "^[A-Za-z][A-Za-z0-9_-]{0,127}$" }])),
writesPerformed: { enum: [0, 1] },
confirmationRequired: { type: "boolean" },
authority: { const: projectionAuthority },
}, ["status", "writesPerformed", "authority"]);
export const RECEIZ_V125_TRUST_MCP_TOOLS = Object.freeze(RECEIZ_V125_TRUST_MCP_TOOL_NAMES.map((name) => Object.freeze({
name,
description: (name.startsWith("receiz_v125_subject_message_") ? "Supported thread effect: close only; encrypted message effects are rejected. " : "") + "Invoke one generic Receiz v125 proof operation through opaque trusted-host Reference custody. MCP is not authority; the enclosing sealed Receiz proof object, exact accepted heads, Receiz-ID/PBI authorship, and verified appends remain authority.",
inputSchema: inputSchema(name),
outputSchema: isReadOnly(name)
? { ...resultSchema, properties: { ...resultSchema.properties, writesPerformed: { const: 0 } } }
: resultSchema,
})));
function canonical(value) {
if (value === null || typeof value === "string" || typeof value === "boolean" || typeof value === "number")
return JSON.stringify(value);
if (Array.isArray(value))
return `[${value.map(canonical).join(",")}]`;
if (value && typeof value === "object") {
const record = value;
return `{${Object.keys(record).sort().map((key) => `${JSON.stringify(key)}:${canonical(record[key])}`).join(",")}}`;
}
throw new TypeError("V125_TRUST_MCP_CANONICAL_INPUT_INVALID");
}
function requiredText(value, code) {
if (typeof value !== "string" || value.length < 1 || value.length > 512 || value !== value.trim())
throw new TypeError(code);
return value;
}
function optionalText(value, code) {
return value === undefined ? null : requiredText(value, code);
}
export function assertReceizV125TrustMcpProjection(value, readOnly) {
if (!value || typeof value !== "object" || Array.isArray(value)
|| Object.keys(value).some((key) => !RESULT_FIELDS.has(key))) {
throw new TypeError("V125_TRUST_MCP_RESULT_INVALID");
}
if (value.writesPerformed !== 0 && value.writesPerformed !== 1)
throw new TypeError("V125_TRUST_MCP_RESULT_INVALID");
if (typeof value.status !== "string")
throw new TypeError("V125_TRUST_MCP_RESULT_INVALID");
if (readOnly && value.writesPerformed !== 0)
throw new TypeError("V125_TRUST_MCP_READ_ONLY_WRITES_FORBIDDEN");
for (const key of RESULT_REFERENCE_FIELDS) {
if (key in value)
requiredText(value[key], "V125_TRUST_MCP_RESULT_INVALID");
}
for (const key of RESULT_DIGEST_FIELDS) {
if (key in value && (typeof value[key] !== "string" || !/^[0-9a-f]{64}$/u.test(value[key]))) {
throw new TypeError("V125_TRUST_MCP_RESULT_INVALID");
}
}
for (const key of RESULT_TOKEN_FIELDS) {
if (key in value && (typeof value[key] !== "string" || !/^[A-Za-z][A-Za-z0-9_-]{0,127}$/u.test(value[key]))) {
throw new TypeError("V125_TRUST_MCP_RESULT_INVALID");
}
}
if (("confirmationRequired" in value && typeof value.confirmationRequired !== "boolean")
|| ("authority" in value && canonical(value.authority) !== canonical(projectionAuthority))) {
throw new TypeError("V125_TRUST_MCP_RESULT_INVALID");
}
}
export async function callReceizV125TrustMcpOperation(input) {
if (!RECEIZ_V125_TRUST_MCP_TOOL_NAMES.includes(input.name)) {
throw new TypeError("V125_TRUST_MCP_TOOL_UNKNOWN");
}
const operation = input.name;
const allowedFields = new Set(isReadOnly(operation)
? ["proofReference", "selectedKai"]
: ["proofReference", "selectedKai", "idempotencyKey", "confirmationDigest"]);
if (!input.args || typeof input.args !== "object" || Array.isArray(input.args)
|| Object.keys(input.args).some((key) => !allowedFields.has(key)))
throw new TypeError("V125_TRUST_MCP_INPUT_INVALID");
const proofReference = requiredText(input.args.proofReference, "V125_TRUST_MCP_PROOF_REFERENCE_REQUIRED");
const selectedKai = optionalText(input.args.selectedKai, "V125_TRUST_MCP_KAI_INVALID");
if (selectedKai !== null && !/^(0|[1-9][0-9]*)$/u.test(selectedKai))
throw new TypeError("V125_TRUST_MCP_KAI_INVALID");
const idempotencyKey = isReadOnly(operation)
? null
: requiredText(input.args.idempotencyKey, "V125_TRUST_MCP_IDEMPOTENCY_REQUIRED");
if (!input.host) {
return Object.freeze({
status: "unavailable",
code: "V125_TRUST_HOST_REQUIRED",
missingBoundary: "trusted-host-proof-custody",
writesPerformed: 0,
authority: projectionAuthority,
});
}
if (!isReceizV125TrustMcpHost(input.host))
throw new TypeError("V125_TRUST_MCP_CANONICAL_HOST_REQUIRED");
if (input.runtimeScope)
assertReceizV125TrustMcpHostScope(input.host, input.runtimeScope);
const confirmationDigest = optionalText(input.args.confirmationDigest, "V125_TRUST_MCP_CONFIRMATION_INVALID");
const result = await input.host({ operation, proofReference, selectedKai, idempotencyKey, confirmationDigest });
assertReceizV125TrustMcpProjection(result, isReadOnly(operation));
return Object.freeze({ ...structuredClone(result), authority: projectionAuthority });
}
//# sourceMappingURL=v125TrustOperations.js.map