UNPKG

@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
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