@receiz/mcp-server
Version:
MCP server for agents building and verifying Receiz proof-native applications through the canonical Receiz SDK rails.
74 lines • 3.96 kB
JavaScript
import { open, readFile, realpath } from "node:fs/promises";
import { createHash } from "node:crypto";
import { basename, isAbsolute, relative, resolve } from "node:path";
import { verifyReceizArtifact } from "@receiz/sdk";
/** A digest-bound file reference locates bytes; only the existing verifier
* establishes artifact truth. No serialized admission/session is restored. */
export function createReceizDeviceMaterialHost(workspace) {
const readExact = async (reference, maxBytes) => {
const match = /^receiz:file:([a-f0-9]{64}):(.+)$/.exec(reference);
if (!match)
throw Error("RECEIZ_DEVICE_FILE_REFERENCE_REQUIRED");
const root = await realpath(workspace);
const path = await realpath(resolve(root, match[2]));
const rel = relative(root, path);
if (rel === ".." || rel.startsWith("../") || rel.startsWith("..\\") || isAbsolute(rel))
throw Error("RECEIZ_DEVICE_WORKSPACE_REQUIRED");
if (maxBytes !== undefined && (!Number.isSafeInteger(maxBytes) || maxBytes < 1))
throw Error("RECEIZ_DEVICE_FILE_LIMIT_INVALID");
let exactBytes;
if (maxBytes === undefined)
exactBytes = new Uint8Array(await readFile(path));
else {
const handle = await open(path, "r");
try {
const chunks = [];
let total = 0;
for (;;) {
const chunk = Buffer.alloc(Math.min(65536, maxBytes - total + 1));
const { bytesRead } = await handle.read(chunk, 0, chunk.length, null);
if (!bytesRead)
break;
total += bytesRead;
if (total > maxBytes)
throw Error("RECEIZ_DEVICE_FILE_LIMIT_OPERATIONAL_DENIAL");
chunks.push(chunk.subarray(0, bytesRead));
}
exactBytes = new Uint8Array(Buffer.concat(chunks, total));
}
finally {
await handle.close();
}
}
if (createHash("sha256").update(exactBytes).digest("hex") !== match[1])
throw Error("RECEIZ_DEVICE_SOURCE_CHANGED");
const filename = basename(path);
return { exactBytes, filename, mimeType: "application/octet-stream" };
};
const read = async (reference, maxBytes) => {
const exact = await readExact(reference, maxBytes);
const verification = await verifyReceizArtifact(new File([new Uint8Array(exact.exactBytes).buffer], exact.filename));
if (verification.status !== "verified-artifact")
throw Error("RECEIZ_DEVICE_SOURCE_VERIFICATION_REQUIRED");
return { ...exact, verification };
};
return Object.freeze({
// Exact file location is not proof admission. Replay/recovery callers must
// verify their complete enclosed sources through the SDK before projection.
resolveExactFileReference: readExact,
resolveVerifiedProofReference: read,
resolveProofReference: async (reference) => {
const { exactBytes, filename, mimeType } = await read(reference);
return { exactBytes, filename, mimeType };
},
resolveMaterial: async ({ reference, kind }) => {
if (!["identity-artifact", "subject-source-artifact", "sealed-source-artifact", "sealed-replay-proof-object"].includes(kind))
throw Error("RECEIZ_DEVICE_RUNTIME_CUSTODY_REQUIRED");
const { exactBytes, filename, mimeType, verification } = await read(reference);
return Object.freeze({ schema: "receiz.sealed-artifact-bytes.v124", filename, mimeType,
exactBytesB64u: Buffer.from(exactBytes).toString("base64url"), artifactSha256: verification.artifactDigest.value,
payloadSha256: verification.payloadDigest.value });
},
});
}
//# sourceMappingURL=deviceMaterialHost.js.map