kya_reportPurchase
Report the result of a purchase made with a kyaLabs virtual card. Required after each attempt to complete the audit trail.
Instructions
Report the outcome of a purchase after using a kyaLabs virtual card. Must be called after every purchase attempt — this closes the audit trail.
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| intent_id | Yes | The intent_id returned by kya_getCard | |
| success | Yes | Whether the purchase succeeded | |
| actual_amount | No | Actual amount charged in USD | |
| merchant_name | No | Merchant name as it appeared on the receipt | |
| items | No | Items purchased (free-form description) | |
| order_confirmation | No | Order confirmation number or ID |
Implementation Reference
- src/tools/reportPurchase.ts:103-125 (handler)Main handler function reportPurchase() that dispatches to API or mock implementation based on authentication mode. Checks for consent key, then calls reportViaApi() or reportViaMock().
export async function reportPurchase(input: ReportPurchaseInput): Promise<object> { if (!getStoredConsentKey()) { return { product_name: "kyaLabs", status: "error", message: "Not authenticated. Run kya_getAgentIdentity first to activate your agent, or set KYA_API_KEY in your MCP config.", }; } if (api.isApiMode()) { try { return await reportViaApi(input); } catch (err) { return { product_name: "kyaLabs", status: "error", message: err instanceof Error ? err.message : String(err), }; } } return reportViaMock(input); } - src/tools/reportPurchase.ts:15-44 (helper)API-mode implementation: reportViaApi() — calls the remote API's reportTransaction and getBalance endpoints to record the purchase outcome.
async function reportViaApi(input: ReportPurchaseInput): Promise<object> { const { intent_id, success, actual_amount, merchant_name } = input; if (!success) { const tx = await api.reportTransaction(intent_id, merchant_name, undefined, 0); const balance = await api.getBalance(); return { product_name: "kyaLabs", status: "recorded", intent_match: null, transaction_id: tx.id, remaining_balance: balance.available_cents / 100, message: "Purchase reported as failed. No amount deducted.", }; } const amountCents = actual_amount != null ? Math.round(actual_amount * 100) : 0; const tx = await api.reportTransaction(intent_id, merchant_name, undefined, amountCents); const balance = await api.getBalance(); return { product_name: "kyaLabs", status: "recorded", intent_match: tx.intent_match, ...(tx.intent_mismatch_reason && { intent_mismatch_reason: tx.intent_mismatch_reason }), transaction_id: tx.id, remaining_balance: balance.available_cents / 100, actual_amount: amountCents / 100, }; } - src/tools/reportPurchase.ts:46-101 (helper)Mock-mode implementation: reportViaMock() — uses in-memory store to record the purchase outcome, validate intent status, deduct balance, and determine intent match/mismatch.
function reportViaMock(input: ReportPurchaseInput): object { const { intent_id, success, actual_amount, merchant_name, items, order_confirmation } = input; const intent = getIntent(intent_id); if (!intent) { return { product_name: "kyaLabs", status: "error", message: `Intent ${intent_id} not found.`, }; } if (intent.status !== "pending") { return { product_name: "kyaLabs", status: "error", message: `Intent ${intent_id} has already been reported (status: ${intent.status}).`, }; } if (!success) { intent.status = "failed"; updateIntent(intent); return { product_name: "kyaLabs", status: "recorded", intent_match: null, transaction_id: randomUUID(), remaining_balance: getBalance(), message: "Purchase reported as failed. No amount deducted.", }; } const charged = actual_amount ?? intent.estimated_amount; const tolerance = intent.estimated_amount * 0.2; const diff = Math.abs(charged - intent.estimated_amount); const intent_match = diff <= tolerance ? "match" : "mismatch"; deductBalance(charged); intent.status = "completed"; intent.actual_amount = charged; updateIntent(intent); return { product_name: "kyaLabs", status: "recorded", intent_match, transaction_id: randomUUID(), remaining_balance: getBalance(), ...(merchant_name && { merchant_name }), ...(items && { items }), ...(order_confirmation && { order_confirmation }), estimated_amount: intent.estimated_amount, actual_amount: charged, }; } - src/tools/reportPurchase.ts:6-13 (schema)TypeScript interface ReportPurchaseInput defining the input schema for the reportPurchase function.
export interface ReportPurchaseInput { intent_id: string; success: boolean; actual_amount?: number; merchant_name?: string; items?: string; order_confirmation?: string; } - src/index.ts:207-231 (registration)Registration of the 'kya_reportPurchase' tool on the MCP server with Zod schema validation for inputs and handler callback that delegates to reportPurchase().
server.tool( "kya_reportPurchase", "Report the outcome of a purchase after using a kyaLabs virtual card. Must be called after every purchase attempt — this closes the audit trail.", { intent_id: z.string().uuid().describe("The intent_id returned by kya_getCard"), success: z.boolean().describe("Whether the purchase succeeded"), actual_amount: z.number().positive().max(500).optional().describe("Actual amount charged in USD"), merchant_name: z.string().max(500).optional().describe("Merchant name as it appeared on the receipt"), items: z.string().max(2000).optional().describe("Items purchased (free-form description)"), order_confirmation: z.string().max(200).optional().describe("Order confirmation number or ID"), }, async ({ intent_id, success, actual_amount, merchant_name, items, order_confirmation }) => { const result = await reportPurchase({ intent_id, success, actual_amount, merchant_name, items, order_confirmation, }); return { content: [{ type: "text", text: JSON.stringify(result, null, 2) }], }; } );