UNPKG

@receiz/mcp-server

Version:

MCP server for agents building and verifying Receiz proof-native applications through the canonical Receiz SDK rails.

118 lines • 7.02 kB
import { createHash } from "node:crypto"; const object = (properties, required = []) => ({ type: "object", additionalProperties: false, properties, required }); const text = (description) => ({ type: "string", description }); export const RECEIZ_V123_MCP_TOOL_NAMES = Object.freeze([ "receiz_v123_world_plan_command_v122", "receiz_v123_world_plan_transaction_v122", "receiz_v123_value_execute_settlement", "receiz_v123_value_execute_reserve", "receiz_v123_value_execution_by_idempotency", "receiz_v123_subject_resolve_namespaces", "receiz_v123_identity_exchange_proof_authority", "receiz_v123_auth_granted_scopes", ]); const mutationInput = object({ input: { type: "object", description: "Exact SDK input. Secret fields remain process-local and are redacted from MCP output." }, confirmation: text("Exact confirmation digest returned by the preview call."), }, ["input"]); export const RECEIZ_V123_MCP_TOOLS = RECEIZ_V123_MCP_TOOL_NAMES.map((name) => ({ name, description: name.includes("value_execute") ? "Execute exact Phi through one explicit Settlement or Reserve rail. Requires confirmation; committed, zero-write, and unknown are preserved exactly. USD is deterministic display only. MCP is not authority." : name.includes("exchange_proof") ? "Exchange an independently verifiable Receiz identity artifact and explicit in-application consent for short-lived scoped authority without redirecting the user to receiz.com. Requires confirmation; bearer and artifact bytes are never returned to MCP context. MCP is not authority." : "Receiz v123 universal execution operation projected through the canonical SDK. The proof object and accepted append remain authority. MCP is not authority.", inputSchema: name.includes("value_execute") || name.includes("exchange_proof") ? mutationInput : object({ input: { type: "object", description: "Exact canonical SDK input." } }, name.includes("granted_scopes") ? [] : ["input"]), outputSchema: { type: "object", additionalProperties: true }, })); const authorityCache = new WeakMap(); function canonical(value) { if (value === null || typeof value === "string" || typeof value === "boolean") return JSON.stringify(value); if (typeof value === "number" && Number.isFinite(value)) return JSON.stringify(value); if (Array.isArray(value)) return `[${value.map(canonical).join(",")}]`; if (value && typeof value === "object") return `{${Object.keys(value).sort().map((key) => `${JSON.stringify(key)}:${canonical(value[key])}`).join(",")}}`; return JSON.stringify(String(value)); } function confirmationDigest(name, value) { return createHash("sha256").update(canonical({ schema: "receiz.mcp.mutation-confirmation.v123", name, value })).digest("hex"); } function inputObject(args) { const value = args.input ?? args; return value && typeof value === "object" && !Array.isArray(value) ? value : {}; } function redact(value) { if (Array.isArray(value)) return value.map(redact); if (!value || typeof value !== "object") return value; const output = {}; for (const [key, child] of Object.entries(value)) { if (/^(accessToken|token|artifact|artifactBase64|exactBytes|exactBytesB64u|privateKey|signature|ciphertext)$/i.test(key)) continue; output[key] = redact(child); } return output; } function previewOrConfirm(name, args, value) { const digest = confirmationDigest(name, value); if (args.confirmation === undefined) return { confirmationRequired: true, confirmationDigest: digest, writesPerformed: 0, secretMaterialReturned: false }; if (args.confirmation !== digest) throw new TypeError("V123_MCP_CONFIRMATION_INVALID"); return digest; } function cachedAuthority(client, input) { if (input.authority && typeof input.authority === "object") return input.authority; const digest = typeof input.authorityDigest === "string" ? input.authorityDigest : ""; const authority = authorityCache.get(client)?.get(digest); if (!authority) throw new TypeError("V123_MCP_AUTHORITY_REQUIRED"); return authority; } export async function callReceizV123McpOperation(client, name, args) { const input = inputObject(args); switch (name) { case "receiz_v123_world_plan_command_v122": return client.world.planCommandV122(input); case "receiz_v123_world_plan_transaction_v122": return client.world.planTransactionV122(input); case "receiz_v123_subject_resolve_namespaces": return client.subjects.resolveNamespaces(input); case "receiz_v123_auth_granted_scopes": { const rails = Array.isArray(input.rails) ? input.rails.filter((rail) => typeof rail === "string") : []; const grantedScopes = await client.auth.grantedScopes(); return { grantedScopes, missingScopes: rails.length ? await client.auth.missingScopesForRails(...rails) : [], canUseRails: rails.length ? await client.auth.canUseRails(...rails) : true }; } case "receiz_v123_value_execution_by_idempotency": return redact(await client.value.executionByIdempotencyKey(String(input.idempotencyKey ?? ""), input.authorityDigest ? cachedAuthority(client, input) : undefined)); case "receiz_v123_identity_exchange_proof_authority": { const confirmation = previewOrConfirm(name, args, input); if (typeof confirmation !== "string") return confirmation; const exactBytes = new Uint8Array(Buffer.from(String(input.artifactBase64 ?? ""), "base64")); const authority = await client.identity.exchangeProofAuthority({ artifact: exactBytes, challenge: input.challenge, applicationId: input.applicationId, scopes: input.scopes }); if (authority && typeof authority === "object" && typeof authority.authorityDigest === "string") { const cache = authorityCache.get(client) ?? new Map(); cache.set(String(authority.authorityDigest), authority); authorityCache.set(client, cache); } return redact(authority); } case "receiz_v123_value_execute_settlement": case "receiz_v123_value_execute_reserve": { const confirmation = previewOrConfirm(name, args, { intent: input.intent, authorityDigest: input.authority?.authorityDigest ?? input.authorityDigest }); if (typeof confirmation !== "string") return confirmation; const authority = cachedAuthority(client, input); const outcome = name.endsWith("settlement") ? await client.value.executeSettlement(input.intent, authority) : await client.value.executeReserve(input.intent, authority); return redact(outcome); } default: throw new Error("V123_MCP_TOOL_UNKNOWN"); } } //# sourceMappingURL=v123Operations.js.map