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