@peac/mappings-mcp 0.12.0 → 0.12.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/budget.ts","../src/meta.ts","../src/guard.ts","../src/index.ts"],"names":["CARRIER_TRANSPORT_LIMITS","validateCarrierConstraints","PeacEvidenceCarrierSchema","verifyReceiptRefConsistency","computeReceiptRef"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Budget enforcement utilities for MCP tool calls\n * Uses bigint for all currency calculations to avoid floating-point errors\n */\n\nexport interface BudgetConfig {\n /** Maximum cost per single call in minor currency units (e.g., cents for USD) */\n maxPerCallMinor?: bigint;\n /** Maximum total cost per day in minor currency units */\n maxDailyMinor?: bigint;\n /** Maximum total cost per month in minor currency units */\n maxMonthlyMinor?: bigint;\n /** Currency code (must match at runtime, e.g., 'USD', 'INR') */\n currency: string;\n}\n\nexport interface BudgetResult {\n /** Whether the cost is allowed within budget limits */\n allowed: boolean;\n /**\n * Remaining budget in minor units (after this operation).\n * - When allowed: the minimum remaining across all applicable limits\n * - When denied: 0n (never negative)\n * - When unbounded: undefined (check `unbounded` flag instead)\n */\n remainingMinor?: bigint;\n /**\n * True when no budget limits are configured.\n * In this case, remainingMinor is undefined.\n */\n unbounded?: boolean;\n /** Error code if not allowed */\n code?: 'budget_exceeded' | 'currency_mismatch';\n /** Human-readable reason if not allowed */\n reason?: string;\n}\n\n/**\n * Check if a cost is within budget.\n * Pure, deterministic function - caller tracks time windows externally.\n *\n * @param spentMinor - Amount already spent in minor units (e.g., cents)\n * @param costMinor - Cost of current operation in minor units\n * @param currency - Currency code (must match config.currency)\n * @param config - Budget configuration\n * @returns Result indicating whether cost is allowed and remaining budget\n *\n * @example\n * ```typescript\n * const config: BudgetConfig = {\n * maxPerCallMinor: 500n, // $5.00 max per call\n * maxDailyMinor: 10000n, // $100.00 max per day\n * currency: 'USD'\n * };\n *\n * const result = checkBudget(\n * 8500n, // Already spent $85.00 today\n * 1000n, // Current call costs $10.00\n * 'USD',\n * config\n * );\n *\n * if (result.allowed) {\n * console.log(`Allowed. Remaining: ${result.remainingMinor} cents`);\n * } else {\n * console.log(`Denied: ${result.reason}`);\n * }\n * ```\n */\nexport function checkBudget(\n spentMinor: bigint,\n costMinor: bigint,\n currency: string,\n config: BudgetConfig\n): BudgetResult {\n // Currency mismatch check\n if (currency !== config.currency) {\n return {\n allowed: false,\n remainingMinor: 0n,\n code: 'currency_mismatch',\n reason: `Currency mismatch: expected ${config.currency}, got ${currency}`,\n };\n }\n\n // Check per-call limit\n if (config.maxPerCallMinor !== undefined && costMinor > config.maxPerCallMinor) {\n return {\n allowed: false,\n remainingMinor: 0n, // Never negative - clamp to 0\n code: 'budget_exceeded',\n reason: `Per-call limit exceeded: cost ${costMinor} > limit ${config.maxPerCallMinor}`,\n };\n }\n\n // Check daily limit (if configured)\n if (config.maxDailyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxDailyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxDailyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Daily limit exceeded: total ${newTotal} > limit ${config.maxDailyMinor}`,\n };\n }\n }\n\n // Check monthly limit (if configured)\n if (config.maxMonthlyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxMonthlyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxMonthlyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Monthly limit exceeded: total ${newTotal} > limit ${config.maxMonthlyMinor}`,\n };\n }\n }\n\n // Calculate remaining budget (how much can be spent in future operations)\n // This is the minimum of:\n // 1. Per-call limit (max single operation)\n // 2. Remaining daily budget\n // 3. Remaining monthly budget\n const remainingCandidates: bigint[] = [];\n\n if (config.maxPerCallMinor !== undefined) {\n remainingCandidates.push(config.maxPerCallMinor);\n }\n\n if (config.maxDailyMinor !== undefined) {\n const dailyRemaining = config.maxDailyMinor - (spentMinor + costMinor);\n remainingCandidates.push(dailyRemaining);\n }\n\n if (config.maxMonthlyMinor !== undefined) {\n const monthlyRemaining = config.maxMonthlyMinor - (spentMinor + costMinor);\n remainingCandidates.push(monthlyRemaining);\n }\n\n // Return the most restrictive limit\n if (remainingCandidates.length === 0) {\n // No limits configured - unbounded\n return {\n allowed: true,\n unbounded: true,\n };\n }\n\n const remainingMinor = remainingCandidates.reduce((min, val) => (val < min ? val : min));\n\n return {\n allowed: true,\n remainingMinor,\n };\n}\n","/**\n * MCP _meta carrier format (DD-125).\n *\n * Attach and extract PEAC evidence carriers using MCP _meta keys.\n * Uses reverse-DNS keys under \"org.peacprotocol/\" prefix.\n *\n * New format (v0.11.1+):\n * _meta[\"org.peacprotocol/receipt_ref\"] = \"sha256:...\"\n * _meta[\"org.peacprotocol/receipt_jws\"] = \"eyJ...\"\n *\n * Legacy format (v0.10.13):\n * _meta[\"org.peacprotocol/receipt\"] = \"eyJ...\" (JWS only, no receipt_ref)\n */\n\nimport type {\n PeacEvidenceCarrier,\n CarrierMeta,\n CarrierValidationResult,\n CarrierAdapter,\n} from '@peac/kernel';\nimport {\n PeacEvidenceCarrierSchema,\n computeReceiptRef,\n validateCarrierConstraints,\n verifyReceiptRefConsistency,\n CARRIER_TRANSPORT_LIMITS,\n} from '@peac/schema';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** _meta key for receipt reference (v0.11.1+) */\nexport const META_KEY_RECEIPT_REF = 'org.peacprotocol/receipt_ref' as const;\n\n/** _meta key for receipt JWS (v0.11.1+) */\nexport const META_KEY_RECEIPT_JWS = 'org.peacprotocol/receipt_jws' as const;\n\n/** _meta key for agent ID (v0.10.13+, unchanged) */\nexport const META_KEY_AGENT_ID = 'org.peacprotocol/agent_id' as const;\n\n/** _meta key for verification timestamp (v0.10.13+, unchanged) */\nexport const META_KEY_VERIFIED_AT = 'org.peacprotocol/verified_at' as const;\n\n/** _meta key for receipt URL locator hint (v0.11.2+, DD-135) */\nexport const META_KEY_RECEIPT_URL = 'org.peacprotocol/receipt_url' as const;\n\n/** Legacy _meta key for receipt JWS (v0.10.13, DD-125) */\nexport const META_KEY_LEGACY_RECEIPT = 'org.peacprotocol/receipt' as const;\n\n/** Maximum carrier size for MCP _meta (64 KB, DD-127) */\nexport const MCP_MAX_CARRIER_SIZE = CARRIER_TRANSPORT_LIMITS.mcp;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** MCP _meta object */\nexport type McpMeta = Record<string, unknown>;\n\n/** MCP JSON-RPC result with _meta */\nexport interface McpResultLike {\n _meta?: McpMeta;\n [key: string]: unknown;\n}\n\n/** Options for attachReceiptToMeta */\nexport interface AttachMetaOptions {\n /** Use legacy format (v0.10.13 peac_receipt key). Default: false */\n legacyFormat?: boolean;\n /** Agent ID to include in _meta */\n agentId?: string;\n /** Verification timestamp (ISO 8601) */\n verifiedAt?: string;\n}\n\n/** Result of extraction */\nexport interface McpExtractResult {\n receipts: PeacEvidenceCarrier[];\n meta: CarrierMeta;\n}\n\n/** Async extraction result with consistency violations */\nexport interface McpExtractAsyncResult extends McpExtractResult {\n violations: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Attach\n// ---------------------------------------------------------------------------\n\n/**\n * Attach PEAC evidence carrier to MCP _meta.\n *\n * Default format (v0.11.1+): writes receipt_ref and receipt_jws as separate keys.\n * Legacy format (opts.legacyFormat): writes single \"receipt\" key (DD-125 phase 1).\n */\nexport function attachReceiptToMeta(\n result: McpResultLike,\n carrier: PeacEvidenceCarrier,\n opts?: AttachMetaOptions\n): McpResultLike {\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n const validation = validateCarrierConstraints(carrier, meta);\n if (!validation.valid) {\n throw new Error(`Carrier constraint violation: ${validation.violations.join('; ')}`);\n }\n\n if (!result._meta) {\n result._meta = {};\n }\n\n if (opts?.legacyFormat) {\n // DD-125 legacy format: single JWS string\n if (carrier.receipt_jws) {\n result._meta[META_KEY_LEGACY_RECEIPT] = carrier.receipt_jws;\n }\n } else {\n // v0.11.1+ carrier format\n result._meta[META_KEY_RECEIPT_REF] = carrier.receipt_ref;\n if (carrier.receipt_jws) {\n result._meta[META_KEY_RECEIPT_JWS] = carrier.receipt_jws;\n }\n if (carrier.receipt_url) {\n result._meta[META_KEY_RECEIPT_URL] = carrier.receipt_url;\n }\n }\n\n // Optional metadata fields (unchanged from v0.10.13)\n if (opts?.agentId) {\n result._meta[META_KEY_AGENT_ID] = opts.agentId;\n }\n if (opts?.verifiedAt) {\n result._meta[META_KEY_VERIFIED_AT] = opts.verifiedAt;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Extract (sync: structural validation only)\n// ---------------------------------------------------------------------------\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (sync).\n *\n * Reads in order (DD-125):\n * 1. New carrier keys (receipt_ref + receipt_jws)\n * 2. Legacy key (org.peacprotocol/receipt, v0.10.13)\n *\n * For legacy format, computes receipt_ref from the JWS to return a proper\n * PeacEvidenceCarrier (Polish B). Note: this requires async for the hash,\n * so the sync version uses a placeholder receipt_ref for legacy and marks\n * it in the meta. Use extractReceiptFromMetaAsync for full validation.\n */\nexport function extractReceiptFromMeta(result: McpResultLike): McpExtractResult | null {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n return { receipts: [parsed.data as PeacEvidenceCarrier], meta };\n }\n }\n\n // 2. Try legacy format (v0.10.13, DD-125 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Legacy format has JWS only; we can't compute receipt_ref synchronously.\n // Return the JWS in a carrier with a placeholder ref that extractAsync will fix.\n // For sync extraction, we skip schema validation of receipt_ref since we can't\n // compute it without async. Return the raw data and let async handle integrity.\n return {\n receipts: [\n {\n receipt_ref:\n 'sha256:0000000000000000000000000000000000000000000000000000000000000000' as PeacEvidenceCarrier['receipt_ref'],\n receipt_jws: legacyReceipt,\n },\n ],\n meta: { ...meta, redaction: ['legacy_receipt_ref_pending'] },\n };\n }\n\n return null;\n}\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (async, DD-129).\n *\n * Performs structural validation AND receipt_ref consistency check.\n * For legacy format (v0.10.13), computes receipt_ref from JWS (Polish B).\n */\nexport async function extractReceiptFromMetaAsync(\n result: McpResultLike\n): Promise<McpExtractAsyncResult | null> {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n const validCarrier = parsed.data as PeacEvidenceCarrier;\n const error = await verifyReceiptRefConsistency(validCarrier);\n const violations = error ? [error] : [];\n return {\n receipts: error ? [] : [validCarrier],\n meta,\n violations,\n };\n }\n }\n\n // 2. Try legacy format (v0.10.13, DD-125 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Compute receipt_ref from legacy JWS\n const computedRef = await computeReceiptRef(legacyReceipt);\n const carrier: PeacEvidenceCarrier = {\n receipt_ref: computedRef,\n receipt_jws: legacyReceipt,\n };\n return { receipts: [carrier], meta, violations: [] };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// McpCarrierAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * CarrierAdapter implementation for MCP _meta format.\n */\nexport class McpCarrierAdapter implements CarrierAdapter<McpResultLike, McpResultLike> {\n extract(input: McpResultLike): { receipts: PeacEvidenceCarrier[]; meta: CarrierMeta } | null {\n return extractReceiptFromMeta(input);\n }\n\n attach(\n output: McpResultLike,\n carriers: PeacEvidenceCarrier[],\n meta?: CarrierMeta\n ): McpResultLike {\n // Attach first carrier (MCP typically carries one receipt per response)\n if (carriers.length > 0) {\n attachReceiptToMeta(output, carriers[0]);\n }\n return output;\n }\n\n validateConstraints(carrier: PeacEvidenceCarrier, meta: CarrierMeta): CarrierValidationResult {\n return validateCarrierConstraints(carrier, meta);\n }\n}\n","/**\n * MCP _meta reserved key guard.\n *\n * Per MCP specification (2025-11-25), the reserved prefix rule is:\n * \"Any prefix where the second label is `modelcontextprotocol` or `mcp`\n * is reserved.\"\n *\n * The prefix is the segment before the first `/`, split by `.` into labels.\n * Only the second label (labels[1], 0-indexed) determines reservation.\n *\n * Examples:\n * \"dev.mcp/anything\" -> RESERVED (2nd label = mcp)\n * \"io.modelcontextprotocol/data\" -> RESERVED (2nd label = modelcontextprotocol)\n * \"com.mcp.tools/data\" -> RESERVED (2nd label = mcp)\n * \"tools.mcp.com/data\" -> RESERVED (2nd label = mcp)\n * \"mcp.dev/anything\" -> NOT reserved (2nd label = dev)\n * \"modelcontextprotocol.io/data\" -> NOT reserved (2nd label = io)\n * \"com.example.mcp/data\" -> NOT reserved (2nd label = example)\n * \"org.peacprotocol/receipt_ref\" -> NOT reserved (2nd label = peacprotocol)\n */\n\nconst MCP_RESERVED_SECOND_LABELS = ['modelcontextprotocol', 'mcp'];\n\n/**\n * Assert that a _meta key does not use an MCP-reserved prefix.\n *\n * A prefix is reserved when its second label (labels[1], 0-indexed)\n * equals \"mcp\" or \"modelcontextprotocol\" (case-insensitive).\n *\n * @throws Error if the key uses a reserved prefix\n */\nexport function assertNotMcpReservedKey(key: string): void {\n const slashIndex = key.indexOf('/');\n if (slashIndex === -1) return; // No prefix = not reserved\n\n const prefix = key.substring(0, slashIndex);\n const labels = prefix.split('.');\n\n if (labels.length < 2) return; // Single label = no second label = not reserved\n\n if (MCP_RESERVED_SECOND_LABELS.includes(labels[1].toLowerCase())) {\n throw new Error(\n `Reserved MCP _meta key prefix: ${key} (second label \"${labels[1]}\" is reserved per MCP spec)`\n );\n }\n}\n\n/**\n * Check if a _meta key uses an MCP-reserved prefix (non-throwing).\n */\nexport function isMcpReservedKey(key: string): boolean {\n try {\n assertNotMcpReservedKey(key);\n return false;\n } catch {\n return true;\n }\n}\n","/**\n * @peac/mappings-mcp\n *\n * Model Context Protocol (MCP) integration for PEAC.\n * Attach and extract PEAC evidence carriers via MCP _meta keys (DD-125).\n */\n\n// Budget enforcement\nexport * from './budget';\n\n// Carrier _meta format (v0.11.1+ Evidence Carrier Contract)\nexport type {\n McpMeta,\n McpResultLike,\n AttachMetaOptions,\n McpExtractResult,\n McpExtractAsyncResult,\n} from './meta';\n\nexport {\n attachReceiptToMeta,\n extractReceiptFromMeta,\n extractReceiptFromMetaAsync,\n McpCarrierAdapter,\n META_KEY_RECEIPT_REF,\n META_KEY_RECEIPT_JWS,\n META_KEY_RECEIPT_URL,\n META_KEY_AGENT_ID,\n META_KEY_VERIFIED_AT,\n META_KEY_LEGACY_RECEIPT,\n MCP_MAX_CARRIER_SIZE,\n} from './meta';\n\n// MCP _meta reserved key guard\nexport { assertNotMcpReservedKey, isMcpReservedKey } from './guard';\n\n// ---------------------------------------------------------------------------\n// Legacy API (backward compatible)\n// ---------------------------------------------------------------------------\n\n/**\n * MCP Tool Response\n */\nexport interface MCPToolResponse {\n tool: string;\n result: unknown;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * MCP Tool Response with PEAC receipt (legacy format)\n */\nexport interface MCPToolResponseWithReceipt extends MCPToolResponse {\n peac_receipt?: string;\n}\n\n/**\n * Attach PEAC receipt to MCP tool response (legacy format).\n *\n * Uses `peac_receipt` top-level key. For new integrations, prefer\n * `attachReceiptToMeta()` which uses the _meta carrier format (DD-125).\n *\n * @param response - MCP tool response\n * @param receiptJWS - PEAC receipt JWS\n * @returns MCP tool response with PEAC receipt attached\n */\nexport function attachReceipt(\n response: MCPToolResponse,\n receiptJWS: string\n): MCPToolResponseWithReceipt {\n return {\n ...response,\n peac_receipt: receiptJWS,\n };\n}\n\n/**\n * Extract PEAC receipt from MCP tool response.\n *\n * Reads BOTH legacy `peac_receipt` field AND `_meta` carrier format (DD-125).\n * Prefers _meta format when both are present.\n *\n * @param response - MCP tool response (possibly with receipt)\n * @returns PEAC receipt JWS or null if not present\n */\nexport function extractReceipt(response: MCPToolResponseWithReceipt): string | null {\n // 1. Try _meta carrier format (v0.11.1+)\n if (response._meta) {\n const meta = response._meta as Record<string, unknown>;\n // New format: receipt_jws key\n const jws = meta['org.peacprotocol/receipt_jws'];\n if (typeof jws === 'string' && jws.length > 0) {\n return jws;\n }\n // Legacy _meta format: receipt key (v0.10.13)\n const legacyJws = meta['org.peacprotocol/receipt'];\n if (typeof legacyJws === 'string' && legacyJws.length > 0) {\n return legacyJws;\n }\n }\n\n // 2. Fall back to legacy peac_receipt field\n if (typeof response.peac_receipt === 'string' && response.peac_receipt.length > 0) {\n return response.peac_receipt;\n }\n return null;\n}\n\n/**\n * Check if MCP tool response has a PEAC receipt\n *\n * @param response - MCP tool response\n * @returns true if receipt is present\n */\nexport function hasReceipt(response: MCPToolResponseWithReceipt): boolean {\n return extractReceipt(response) !== null;\n}\n\n/**\n * Create MCP tool response with PEAC receipt for paid API calls\n *\n * @param tool - Tool name\n * @param result - Tool execution result\n * @param receiptJWS - PEAC receipt JWS\n * @param metadata - Optional metadata\n * @returns MCP tool response with receipt\n */\nexport function createPaidToolResponse(\n tool: string,\n result: unknown,\n receiptJWS: string,\n metadata?: Record<string, unknown>\n): MCPToolResponseWithReceipt {\n const response: MCPToolResponse = {\n tool,\n result,\n ...(metadata && { metadata }),\n };\n\n return attachReceipt(response, receiptJWS);\n}\n"]}
1
+ {"version":3,"sources":["../src/budget.ts","../src/meta.ts","../src/guard.ts","../src/index.ts"],"names":["CARRIER_TRANSPORT_LIMITS","validateCarrierConstraints","PeacEvidenceCarrierSchema","verifyReceiptRefConsistency","computeReceiptRef"],"mappings":"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","file":"index.cjs","sourcesContent":["/**\n * Budget enforcement utilities for MCP tool calls\n * Uses bigint for all currency calculations to avoid floating-point errors\n */\n\nexport interface BudgetConfig {\n /** Maximum cost per single call in minor currency units (e.g., cents for USD) */\n maxPerCallMinor?: bigint;\n /** Maximum total cost per day in minor currency units */\n maxDailyMinor?: bigint;\n /** Maximum total cost per month in minor currency units */\n maxMonthlyMinor?: bigint;\n /** Currency code (must match at runtime, e.g., 'USD', 'INR') */\n currency: string;\n}\n\nexport interface BudgetResult {\n /** Whether the cost is allowed within budget limits */\n allowed: boolean;\n /**\n * Remaining budget in minor units (after this operation).\n * - When allowed: the minimum remaining across all applicable limits\n * - When denied: 0n (never negative)\n * - When unbounded: undefined (check `unbounded` flag instead)\n */\n remainingMinor?: bigint;\n /**\n * True when no budget limits are configured.\n * In this case, remainingMinor is undefined.\n */\n unbounded?: boolean;\n /** Error code if not allowed */\n code?: 'budget_exceeded' | 'currency_mismatch';\n /** Human-readable reason if not allowed */\n reason?: string;\n}\n\n/**\n * Check if a cost is within budget.\n * Pure, deterministic function - caller tracks time windows externally.\n *\n * @param spentMinor - Amount already spent in minor units (e.g., cents)\n * @param costMinor - Cost of current operation in minor units\n * @param currency - Currency code (must match config.currency)\n * @param config - Budget configuration\n * @returns Result indicating whether cost is allowed and remaining budget\n *\n * @example\n * ```typescript\n * const config: BudgetConfig = {\n * maxPerCallMinor: 500n, // $5.00 max per call\n * maxDailyMinor: 10000n, // $100.00 max per day\n * currency: 'USD'\n * };\n *\n * const result = checkBudget(\n * 8500n, // Already spent $85.00 today\n * 1000n, // Current call costs $10.00\n * 'USD',\n * config\n * );\n *\n * if (result.allowed) {\n * console.log(`Allowed. Remaining: ${result.remainingMinor} cents`);\n * } else {\n * console.log(`Denied: ${result.reason}`);\n * }\n * ```\n */\nexport function checkBudget(\n spentMinor: bigint,\n costMinor: bigint,\n currency: string,\n config: BudgetConfig\n): BudgetResult {\n // Currency mismatch check\n if (currency !== config.currency) {\n return {\n allowed: false,\n remainingMinor: 0n,\n code: 'currency_mismatch',\n reason: `Currency mismatch: expected ${config.currency}, got ${currency}`,\n };\n }\n\n // Check per-call limit\n if (config.maxPerCallMinor !== undefined && costMinor > config.maxPerCallMinor) {\n return {\n allowed: false,\n remainingMinor: 0n, // Never negative - clamp to 0\n code: 'budget_exceeded',\n reason: `Per-call limit exceeded: cost ${costMinor} > limit ${config.maxPerCallMinor}`,\n };\n }\n\n // Check daily limit (if configured)\n if (config.maxDailyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxDailyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxDailyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Daily limit exceeded: total ${newTotal} > limit ${config.maxDailyMinor}`,\n };\n }\n }\n\n // Check monthly limit (if configured)\n if (config.maxMonthlyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxMonthlyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxMonthlyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Monthly limit exceeded: total ${newTotal} > limit ${config.maxMonthlyMinor}`,\n };\n }\n }\n\n // Calculate remaining budget (how much can be spent in future operations)\n // This is the minimum of:\n // 1. Per-call limit (max single operation)\n // 2. Remaining daily budget\n // 3. Remaining monthly budget\n const remainingCandidates: bigint[] = [];\n\n if (config.maxPerCallMinor !== undefined) {\n remainingCandidates.push(config.maxPerCallMinor);\n }\n\n if (config.maxDailyMinor !== undefined) {\n const dailyRemaining = config.maxDailyMinor - (spentMinor + costMinor);\n remainingCandidates.push(dailyRemaining);\n }\n\n if (config.maxMonthlyMinor !== undefined) {\n const monthlyRemaining = config.maxMonthlyMinor - (spentMinor + costMinor);\n remainingCandidates.push(monthlyRemaining);\n }\n\n // Return the most restrictive limit\n if (remainingCandidates.length === 0) {\n // No limits configured - unbounded\n return {\n allowed: true,\n unbounded: true,\n };\n }\n\n const remainingMinor = remainingCandidates.reduce((min, val) => (val < min ? val : min));\n\n return {\n allowed: true,\n remainingMinor,\n };\n}\n","/**\n * MCP _meta carrier format.\n *\n * Attach and extract PEAC evidence carriers using MCP _meta keys.\n * Uses reverse-DNS keys under \"org.peacprotocol/\" prefix.\n *\n * New format (v0.11.1+):\n * _meta[\"org.peacprotocol/receipt_ref\"] = \"sha256:...\"\n * _meta[\"org.peacprotocol/receipt_jws\"] = \"eyJ...\"\n *\n * Legacy format (v0.10.13):\n * _meta[\"org.peacprotocol/receipt\"] = \"eyJ...\" (JWS only, no receipt_ref)\n */\n\nimport type {\n PeacEvidenceCarrier,\n CarrierMeta,\n CarrierValidationResult,\n CarrierAdapter,\n} from '@peac/kernel';\nimport {\n PeacEvidenceCarrierSchema,\n computeReceiptRef,\n validateCarrierConstraints,\n verifyReceiptRefConsistency,\n CARRIER_TRANSPORT_LIMITS,\n} from '@peac/schema';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** _meta key for receipt reference (v0.11.1+) */\nexport const META_KEY_RECEIPT_REF = 'org.peacprotocol/receipt_ref' as const;\n\n/** _meta key for receipt JWS (v0.11.1+) */\nexport const META_KEY_RECEIPT_JWS = 'org.peacprotocol/receipt_jws' as const;\n\n/** _meta key for agent ID (v0.10.13+, unchanged) */\nexport const META_KEY_AGENT_ID = 'org.peacprotocol/agent_id' as const;\n\n/** _meta key for verification timestamp (v0.10.13+, unchanged) */\nexport const META_KEY_VERIFIED_AT = 'org.peacprotocol/verified_at' as const;\n\n/** _meta key for receipt URL locator hint (v0.11.2+) */\nexport const META_KEY_RECEIPT_URL = 'org.peacprotocol/receipt_url' as const;\n\n/** Legacy _meta key for receipt JWS (v0.10.13) */\nexport const META_KEY_LEGACY_RECEIPT = 'org.peacprotocol/receipt' as const;\n\n/** Maximum carrier size for MCP _meta (64 KB) */\nexport const MCP_MAX_CARRIER_SIZE = CARRIER_TRANSPORT_LIMITS.mcp;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** MCP _meta object */\nexport type McpMeta = Record<string, unknown>;\n\n/** MCP JSON-RPC result with _meta */\nexport interface McpResultLike {\n _meta?: McpMeta;\n [key: string]: unknown;\n}\n\n/** Options for attachReceiptToMeta */\nexport interface AttachMetaOptions {\n /** Use legacy format (v0.10.13 peac_receipt key). Default: false */\n legacyFormat?: boolean;\n /** Agent ID to include in _meta */\n agentId?: string;\n /** Verification timestamp (ISO 8601) */\n verifiedAt?: string;\n}\n\n/** Result of extraction */\nexport interface McpExtractResult {\n receipts: PeacEvidenceCarrier[];\n meta: CarrierMeta;\n}\n\n/** Async extraction result with consistency violations */\nexport interface McpExtractAsyncResult extends McpExtractResult {\n violations: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Attach\n// ---------------------------------------------------------------------------\n\n/**\n * Attach PEAC evidence carrier to MCP _meta.\n *\n * Default format (v0.11.1+): writes receipt_ref and receipt_jws as separate keys.\n * Legacy format (opts.legacyFormat): writes single \"receipt\" key (phase 1).\n */\nexport function attachReceiptToMeta(\n result: McpResultLike,\n carrier: PeacEvidenceCarrier,\n opts?: AttachMetaOptions\n): McpResultLike {\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n const validation = validateCarrierConstraints(carrier, meta);\n if (!validation.valid) {\n throw new Error(`Carrier constraint violation: ${validation.violations.join('; ')}`);\n }\n\n if (!result._meta) {\n result._meta = {};\n }\n\n if (opts?.legacyFormat) {\n // legacy format: single JWS string\n if (carrier.receipt_jws) {\n result._meta[META_KEY_LEGACY_RECEIPT] = carrier.receipt_jws;\n }\n } else {\n // v0.11.1+ carrier format\n result._meta[META_KEY_RECEIPT_REF] = carrier.receipt_ref;\n if (carrier.receipt_jws) {\n result._meta[META_KEY_RECEIPT_JWS] = carrier.receipt_jws;\n }\n if (carrier.receipt_url) {\n result._meta[META_KEY_RECEIPT_URL] = carrier.receipt_url;\n }\n }\n\n // Optional metadata fields (unchanged from v0.10.13)\n if (opts?.agentId) {\n result._meta[META_KEY_AGENT_ID] = opts.agentId;\n }\n if (opts?.verifiedAt) {\n result._meta[META_KEY_VERIFIED_AT] = opts.verifiedAt;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Extract (sync: structural validation only)\n// ---------------------------------------------------------------------------\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (sync).\n *\n * Reads in order:\n * 1. New carrier keys (receipt_ref + receipt_jws)\n * 2. Legacy key (org.peacprotocol/receipt, v0.10.13)\n *\n * For legacy format, computes receipt_ref from the JWS to return a proper\n * PeacEvidenceCarrier (Polish B). Note: this requires async for the hash,\n * so the sync version uses a placeholder receipt_ref for legacy and marks\n * it in the meta. Use extractReceiptFromMetaAsync for full validation.\n */\nexport function extractReceiptFromMeta(result: McpResultLike): McpExtractResult | null {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n return { receipts: [parsed.data as PeacEvidenceCarrier], meta };\n }\n }\n\n // 2. Try legacy format (v0.10.13 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Legacy format has JWS only; we can't compute receipt_ref synchronously.\n // Return the JWS in a carrier with a placeholder ref that extractAsync will fix.\n // For sync extraction, we skip schema validation of receipt_ref since we can't\n // compute it without async. Return the raw data and let async handle integrity.\n return {\n receipts: [\n {\n receipt_ref:\n 'sha256:0000000000000000000000000000000000000000000000000000000000000000' as PeacEvidenceCarrier['receipt_ref'],\n receipt_jws: legacyReceipt,\n },\n ],\n meta: { ...meta, redaction: ['legacy_receipt_ref_pending'] },\n };\n }\n\n return null;\n}\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (async).\n *\n * Performs structural validation AND receipt_ref consistency check.\n * For legacy format (v0.10.13), computes receipt_ref from JWS (Polish B).\n */\nexport async function extractReceiptFromMetaAsync(\n result: McpResultLike\n): Promise<McpExtractAsyncResult | null> {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n const validCarrier = parsed.data as PeacEvidenceCarrier;\n const error = await verifyReceiptRefConsistency(validCarrier);\n const violations = error ? [error] : [];\n return {\n receipts: error ? [] : [validCarrier],\n meta,\n violations,\n };\n }\n }\n\n // 2. Try legacy format (v0.10.13 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Compute receipt_ref from legacy JWS\n const computedRef = await computeReceiptRef(legacyReceipt);\n const carrier: PeacEvidenceCarrier = {\n receipt_ref: computedRef,\n receipt_jws: legacyReceipt,\n };\n return { receipts: [carrier], meta, violations: [] };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// McpCarrierAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * CarrierAdapter implementation for MCP _meta format.\n */\nexport class McpCarrierAdapter implements CarrierAdapter<McpResultLike, McpResultLike> {\n extract(input: McpResultLike): { receipts: PeacEvidenceCarrier[]; meta: CarrierMeta } | null {\n return extractReceiptFromMeta(input);\n }\n\n attach(\n output: McpResultLike,\n carriers: PeacEvidenceCarrier[],\n meta?: CarrierMeta\n ): McpResultLike {\n // Attach first carrier (MCP typically carries one receipt per response)\n if (carriers.length > 0) {\n attachReceiptToMeta(output, carriers[0]);\n }\n return output;\n }\n\n validateConstraints(carrier: PeacEvidenceCarrier, meta: CarrierMeta): CarrierValidationResult {\n return validateCarrierConstraints(carrier, meta);\n }\n}\n","/**\n * MCP _meta reserved key guard.\n *\n * Per MCP specification (2025-11-25), the reserved prefix rule is:\n * \"Any prefix where the second label is `modelcontextprotocol` or `mcp`\n * is reserved.\"\n *\n * The prefix is the segment before the first `/`, split by `.` into labels.\n * Only the second label (labels[1], 0-indexed) determines reservation.\n *\n * Examples:\n * \"dev.mcp/anything\" -> RESERVED (2nd label = mcp)\n * \"io.modelcontextprotocol/data\" -> RESERVED (2nd label = modelcontextprotocol)\n * \"com.mcp.tools/data\" -> RESERVED (2nd label = mcp)\n * \"tools.mcp.com/data\" -> RESERVED (2nd label = mcp)\n * \"mcp.dev/anything\" -> NOT reserved (2nd label = dev)\n * \"modelcontextprotocol.io/data\" -> NOT reserved (2nd label = io)\n * \"com.example.mcp/data\" -> NOT reserved (2nd label = example)\n * \"org.peacprotocol/receipt_ref\" -> NOT reserved (2nd label = peacprotocol)\n */\n\nconst MCP_RESERVED_SECOND_LABELS = ['modelcontextprotocol', 'mcp'];\n\n/**\n * Assert that a _meta key does not use an MCP-reserved prefix.\n *\n * A prefix is reserved when its second label (labels[1], 0-indexed)\n * equals \"mcp\" or \"modelcontextprotocol\" (case-insensitive).\n *\n * @throws Error if the key uses a reserved prefix\n */\nexport function assertNotMcpReservedKey(key: string): void {\n const slashIndex = key.indexOf('/');\n if (slashIndex === -1) return; // No prefix = not reserved\n\n const prefix = key.substring(0, slashIndex);\n const labels = prefix.split('.');\n\n if (labels.length < 2) return; // Single label = no second label = not reserved\n\n if (MCP_RESERVED_SECOND_LABELS.includes(labels[1].toLowerCase())) {\n throw new Error(\n `Reserved MCP _meta key prefix: ${key} (second label \"${labels[1]}\" is reserved per MCP spec)`\n );\n }\n}\n\n/**\n * Check if a _meta key uses an MCP-reserved prefix (non-throwing).\n */\nexport function isMcpReservedKey(key: string): boolean {\n try {\n assertNotMcpReservedKey(key);\n return false;\n } catch {\n return true;\n }\n}\n","/**\n * @peac/mappings-mcp\n *\n * Model Context Protocol (MCP) integration for PEAC.\n * Attach and extract PEAC evidence carriers via MCP _meta keys.\n */\n\n// Budget enforcement\nexport * from './budget';\n\n// Carrier _meta format (v0.11.1+ Evidence Carrier Contract)\nexport type {\n McpMeta,\n McpResultLike,\n AttachMetaOptions,\n McpExtractResult,\n McpExtractAsyncResult,\n} from './meta';\n\nexport {\n attachReceiptToMeta,\n extractReceiptFromMeta,\n extractReceiptFromMetaAsync,\n McpCarrierAdapter,\n META_KEY_RECEIPT_REF,\n META_KEY_RECEIPT_JWS,\n META_KEY_RECEIPT_URL,\n META_KEY_AGENT_ID,\n META_KEY_VERIFIED_AT,\n META_KEY_LEGACY_RECEIPT,\n MCP_MAX_CARRIER_SIZE,\n} from './meta';\n\n// MCP _meta reserved key guard\nexport { assertNotMcpReservedKey, isMcpReservedKey } from './guard';\n\n// ---------------------------------------------------------------------------\n// Legacy API (backward compatible)\n// ---------------------------------------------------------------------------\n\n/**\n * MCP Tool Response\n */\nexport interface MCPToolResponse {\n tool: string;\n result: unknown;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * MCP Tool Response with PEAC receipt (legacy format)\n */\nexport interface MCPToolResponseWithReceipt extends MCPToolResponse {\n peac_receipt?: string;\n}\n\n/**\n * Attach PEAC receipt to MCP tool response (legacy format).\n *\n * Uses `peac_receipt` top-level key. For new integrations, prefer\n * `attachReceiptToMeta()` which uses the _meta carrier format.\n *\n * @param response - MCP tool response\n * @param receiptJWS - PEAC receipt JWS\n * @returns MCP tool response with PEAC receipt attached\n */\nexport function attachReceipt(\n response: MCPToolResponse,\n receiptJWS: string\n): MCPToolResponseWithReceipt {\n return {\n ...response,\n peac_receipt: receiptJWS,\n };\n}\n\n/**\n * Extract PEAC receipt from MCP tool response.\n *\n * Reads BOTH legacy `peac_receipt` field AND `_meta` carrier format.\n * Prefers _meta format when both are present.\n *\n * @param response - MCP tool response (possibly with receipt)\n * @returns PEAC receipt JWS or null if not present\n */\nexport function extractReceipt(response: MCPToolResponseWithReceipt): string | null {\n // 1. Try _meta carrier format (v0.11.1+)\n if (response._meta) {\n const meta = response._meta as Record<string, unknown>;\n // New format: receipt_jws key\n const jws = meta['org.peacprotocol/receipt_jws'];\n if (typeof jws === 'string' && jws.length > 0) {\n return jws;\n }\n // Legacy _meta format: receipt key (v0.10.13)\n const legacyJws = meta['org.peacprotocol/receipt'];\n if (typeof legacyJws === 'string' && legacyJws.length > 0) {\n return legacyJws;\n }\n }\n\n // 2. Fall back to legacy peac_receipt field\n if (typeof response.peac_receipt === 'string' && response.peac_receipt.length > 0) {\n return response.peac_receipt;\n }\n return null;\n}\n\n/**\n * Check if MCP tool response has a PEAC receipt\n *\n * @param response - MCP tool response\n * @returns true if receipt is present\n */\nexport function hasReceipt(response: MCPToolResponseWithReceipt): boolean {\n return extractReceipt(response) !== null;\n}\n\n/**\n * Create MCP tool response with PEAC receipt for paid API calls\n *\n * @param tool - Tool name\n * @param result - Tool execution result\n * @param receiptJWS - PEAC receipt JWS\n * @param metadata - Optional metadata\n * @returns MCP tool response with receipt\n */\nexport function createPaidToolResponse(\n tool: string,\n result: unknown,\n receiptJWS: string,\n metadata?: Record<string, unknown>\n): MCPToolResponseWithReceipt {\n const response: MCPToolResponse = {\n tool,\n result,\n ...(metadata && { metadata }),\n };\n\n return attachReceipt(response, receiptJWS);\n}\n"]}
package/dist/index.d.ts CHANGED
@@ -2,7 +2,7 @@
2
2
  * @peac/mappings-mcp
3
3
  *
4
4
  * Model Context Protocol (MCP) integration for PEAC.
5
- * Attach and extract PEAC evidence carriers via MCP _meta keys (DD-125).
5
+ * Attach and extract PEAC evidence carriers via MCP _meta keys.
6
6
  */
7
7
  export * from './budget';
8
8
  export type { McpMeta, McpResultLike, AttachMetaOptions, McpExtractResult, McpExtractAsyncResult, } from './meta';
@@ -27,7 +27,7 @@ export interface MCPToolResponseWithReceipt extends MCPToolResponse {
27
27
  * Attach PEAC receipt to MCP tool response (legacy format).
28
28
  *
29
29
  * Uses `peac_receipt` top-level key. For new integrations, prefer
30
- * `attachReceiptToMeta()` which uses the _meta carrier format (DD-125).
30
+ * `attachReceiptToMeta()` which uses the _meta carrier format.
31
31
  *
32
32
  * @param response - MCP tool response
33
33
  * @param receiptJWS - PEAC receipt JWS
@@ -37,7 +37,7 @@ export declare function attachReceipt(response: MCPToolResponse, receiptJWS: str
37
37
  /**
38
38
  * Extract PEAC receipt from MCP tool response.
39
39
  *
40
- * Reads BOTH legacy `peac_receipt` field AND `_meta` carrier format (DD-125).
40
+ * Reads BOTH legacy `peac_receipt` field AND `_meta` carrier format.
41
41
  * Prefers _meta format when both are present.
42
42
  *
43
43
  * @param response - MCP tool response (possibly with receipt)
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/budget.ts","../src/meta.ts","../src/guard.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Budget enforcement utilities for MCP tool calls\n * Uses bigint for all currency calculations to avoid floating-point errors\n */\n\nexport interface BudgetConfig {\n /** Maximum cost per single call in minor currency units (e.g., cents for USD) */\n maxPerCallMinor?: bigint;\n /** Maximum total cost per day in minor currency units */\n maxDailyMinor?: bigint;\n /** Maximum total cost per month in minor currency units */\n maxMonthlyMinor?: bigint;\n /** Currency code (must match at runtime, e.g., 'USD', 'INR') */\n currency: string;\n}\n\nexport interface BudgetResult {\n /** Whether the cost is allowed within budget limits */\n allowed: boolean;\n /**\n * Remaining budget in minor units (after this operation).\n * - When allowed: the minimum remaining across all applicable limits\n * - When denied: 0n (never negative)\n * - When unbounded: undefined (check `unbounded` flag instead)\n */\n remainingMinor?: bigint;\n /**\n * True when no budget limits are configured.\n * In this case, remainingMinor is undefined.\n */\n unbounded?: boolean;\n /** Error code if not allowed */\n code?: 'budget_exceeded' | 'currency_mismatch';\n /** Human-readable reason if not allowed */\n reason?: string;\n}\n\n/**\n * Check if a cost is within budget.\n * Pure, deterministic function - caller tracks time windows externally.\n *\n * @param spentMinor - Amount already spent in minor units (e.g., cents)\n * @param costMinor - Cost of current operation in minor units\n * @param currency - Currency code (must match config.currency)\n * @param config - Budget configuration\n * @returns Result indicating whether cost is allowed and remaining budget\n *\n * @example\n * ```typescript\n * const config: BudgetConfig = {\n * maxPerCallMinor: 500n, // $5.00 max per call\n * maxDailyMinor: 10000n, // $100.00 max per day\n * currency: 'USD'\n * };\n *\n * const result = checkBudget(\n * 8500n, // Already spent $85.00 today\n * 1000n, // Current call costs $10.00\n * 'USD',\n * config\n * );\n *\n * if (result.allowed) {\n * console.log(`Allowed. Remaining: ${result.remainingMinor} cents`);\n * } else {\n * console.log(`Denied: ${result.reason}`);\n * }\n * ```\n */\nexport function checkBudget(\n spentMinor: bigint,\n costMinor: bigint,\n currency: string,\n config: BudgetConfig\n): BudgetResult {\n // Currency mismatch check\n if (currency !== config.currency) {\n return {\n allowed: false,\n remainingMinor: 0n,\n code: 'currency_mismatch',\n reason: `Currency mismatch: expected ${config.currency}, got ${currency}`,\n };\n }\n\n // Check per-call limit\n if (config.maxPerCallMinor !== undefined && costMinor > config.maxPerCallMinor) {\n return {\n allowed: false,\n remainingMinor: 0n, // Never negative - clamp to 0\n code: 'budget_exceeded',\n reason: `Per-call limit exceeded: cost ${costMinor} > limit ${config.maxPerCallMinor}`,\n };\n }\n\n // Check daily limit (if configured)\n if (config.maxDailyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxDailyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxDailyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Daily limit exceeded: total ${newTotal} > limit ${config.maxDailyMinor}`,\n };\n }\n }\n\n // Check monthly limit (if configured)\n if (config.maxMonthlyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxMonthlyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxMonthlyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Monthly limit exceeded: total ${newTotal} > limit ${config.maxMonthlyMinor}`,\n };\n }\n }\n\n // Calculate remaining budget (how much can be spent in future operations)\n // This is the minimum of:\n // 1. Per-call limit (max single operation)\n // 2. Remaining daily budget\n // 3. Remaining monthly budget\n const remainingCandidates: bigint[] = [];\n\n if (config.maxPerCallMinor !== undefined) {\n remainingCandidates.push(config.maxPerCallMinor);\n }\n\n if (config.maxDailyMinor !== undefined) {\n const dailyRemaining = config.maxDailyMinor - (spentMinor + costMinor);\n remainingCandidates.push(dailyRemaining);\n }\n\n if (config.maxMonthlyMinor !== undefined) {\n const monthlyRemaining = config.maxMonthlyMinor - (spentMinor + costMinor);\n remainingCandidates.push(monthlyRemaining);\n }\n\n // Return the most restrictive limit\n if (remainingCandidates.length === 0) {\n // No limits configured - unbounded\n return {\n allowed: true,\n unbounded: true,\n };\n }\n\n const remainingMinor = remainingCandidates.reduce((min, val) => (val < min ? val : min));\n\n return {\n allowed: true,\n remainingMinor,\n };\n}\n","/**\n * MCP _meta carrier format (DD-125).\n *\n * Attach and extract PEAC evidence carriers using MCP _meta keys.\n * Uses reverse-DNS keys under \"org.peacprotocol/\" prefix.\n *\n * New format (v0.11.1+):\n * _meta[\"org.peacprotocol/receipt_ref\"] = \"sha256:...\"\n * _meta[\"org.peacprotocol/receipt_jws\"] = \"eyJ...\"\n *\n * Legacy format (v0.10.13):\n * _meta[\"org.peacprotocol/receipt\"] = \"eyJ...\" (JWS only, no receipt_ref)\n */\n\nimport type {\n PeacEvidenceCarrier,\n CarrierMeta,\n CarrierValidationResult,\n CarrierAdapter,\n} from '@peac/kernel';\nimport {\n PeacEvidenceCarrierSchema,\n computeReceiptRef,\n validateCarrierConstraints,\n verifyReceiptRefConsistency,\n CARRIER_TRANSPORT_LIMITS,\n} from '@peac/schema';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** _meta key for receipt reference (v0.11.1+) */\nexport const META_KEY_RECEIPT_REF = 'org.peacprotocol/receipt_ref' as const;\n\n/** _meta key for receipt JWS (v0.11.1+) */\nexport const META_KEY_RECEIPT_JWS = 'org.peacprotocol/receipt_jws' as const;\n\n/** _meta key for agent ID (v0.10.13+, unchanged) */\nexport const META_KEY_AGENT_ID = 'org.peacprotocol/agent_id' as const;\n\n/** _meta key for verification timestamp (v0.10.13+, unchanged) */\nexport const META_KEY_VERIFIED_AT = 'org.peacprotocol/verified_at' as const;\n\n/** _meta key for receipt URL locator hint (v0.11.2+, DD-135) */\nexport const META_KEY_RECEIPT_URL = 'org.peacprotocol/receipt_url' as const;\n\n/** Legacy _meta key for receipt JWS (v0.10.13, DD-125) */\nexport const META_KEY_LEGACY_RECEIPT = 'org.peacprotocol/receipt' as const;\n\n/** Maximum carrier size for MCP _meta (64 KB, DD-127) */\nexport const MCP_MAX_CARRIER_SIZE = CARRIER_TRANSPORT_LIMITS.mcp;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** MCP _meta object */\nexport type McpMeta = Record<string, unknown>;\n\n/** MCP JSON-RPC result with _meta */\nexport interface McpResultLike {\n _meta?: McpMeta;\n [key: string]: unknown;\n}\n\n/** Options for attachReceiptToMeta */\nexport interface AttachMetaOptions {\n /** Use legacy format (v0.10.13 peac_receipt key). Default: false */\n legacyFormat?: boolean;\n /** Agent ID to include in _meta */\n agentId?: string;\n /** Verification timestamp (ISO 8601) */\n verifiedAt?: string;\n}\n\n/** Result of extraction */\nexport interface McpExtractResult {\n receipts: PeacEvidenceCarrier[];\n meta: CarrierMeta;\n}\n\n/** Async extraction result with consistency violations */\nexport interface McpExtractAsyncResult extends McpExtractResult {\n violations: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Attach\n// ---------------------------------------------------------------------------\n\n/**\n * Attach PEAC evidence carrier to MCP _meta.\n *\n * Default format (v0.11.1+): writes receipt_ref and receipt_jws as separate keys.\n * Legacy format (opts.legacyFormat): writes single \"receipt\" key (DD-125 phase 1).\n */\nexport function attachReceiptToMeta(\n result: McpResultLike,\n carrier: PeacEvidenceCarrier,\n opts?: AttachMetaOptions\n): McpResultLike {\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n const validation = validateCarrierConstraints(carrier, meta);\n if (!validation.valid) {\n throw new Error(`Carrier constraint violation: ${validation.violations.join('; ')}`);\n }\n\n if (!result._meta) {\n result._meta = {};\n }\n\n if (opts?.legacyFormat) {\n // DD-125 legacy format: single JWS string\n if (carrier.receipt_jws) {\n result._meta[META_KEY_LEGACY_RECEIPT] = carrier.receipt_jws;\n }\n } else {\n // v0.11.1+ carrier format\n result._meta[META_KEY_RECEIPT_REF] = carrier.receipt_ref;\n if (carrier.receipt_jws) {\n result._meta[META_KEY_RECEIPT_JWS] = carrier.receipt_jws;\n }\n if (carrier.receipt_url) {\n result._meta[META_KEY_RECEIPT_URL] = carrier.receipt_url;\n }\n }\n\n // Optional metadata fields (unchanged from v0.10.13)\n if (opts?.agentId) {\n result._meta[META_KEY_AGENT_ID] = opts.agentId;\n }\n if (opts?.verifiedAt) {\n result._meta[META_KEY_VERIFIED_AT] = opts.verifiedAt;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Extract (sync: structural validation only)\n// ---------------------------------------------------------------------------\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (sync).\n *\n * Reads in order (DD-125):\n * 1. New carrier keys (receipt_ref + receipt_jws)\n * 2. Legacy key (org.peacprotocol/receipt, v0.10.13)\n *\n * For legacy format, computes receipt_ref from the JWS to return a proper\n * PeacEvidenceCarrier (Polish B). Note: this requires async for the hash,\n * so the sync version uses a placeholder receipt_ref for legacy and marks\n * it in the meta. Use extractReceiptFromMetaAsync for full validation.\n */\nexport function extractReceiptFromMeta(result: McpResultLike): McpExtractResult | null {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n return { receipts: [parsed.data as PeacEvidenceCarrier], meta };\n }\n }\n\n // 2. Try legacy format (v0.10.13, DD-125 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Legacy format has JWS only; we can't compute receipt_ref synchronously.\n // Return the JWS in a carrier with a placeholder ref that extractAsync will fix.\n // For sync extraction, we skip schema validation of receipt_ref since we can't\n // compute it without async. Return the raw data and let async handle integrity.\n return {\n receipts: [\n {\n receipt_ref:\n 'sha256:0000000000000000000000000000000000000000000000000000000000000000' as PeacEvidenceCarrier['receipt_ref'],\n receipt_jws: legacyReceipt,\n },\n ],\n meta: { ...meta, redaction: ['legacy_receipt_ref_pending'] },\n };\n }\n\n return null;\n}\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (async, DD-129).\n *\n * Performs structural validation AND receipt_ref consistency check.\n * For legacy format (v0.10.13), computes receipt_ref from JWS (Polish B).\n */\nexport async function extractReceiptFromMetaAsync(\n result: McpResultLike\n): Promise<McpExtractAsyncResult | null> {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n const validCarrier = parsed.data as PeacEvidenceCarrier;\n const error = await verifyReceiptRefConsistency(validCarrier);\n const violations = error ? [error] : [];\n return {\n receipts: error ? [] : [validCarrier],\n meta,\n violations,\n };\n }\n }\n\n // 2. Try legacy format (v0.10.13, DD-125 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Compute receipt_ref from legacy JWS\n const computedRef = await computeReceiptRef(legacyReceipt);\n const carrier: PeacEvidenceCarrier = {\n receipt_ref: computedRef,\n receipt_jws: legacyReceipt,\n };\n return { receipts: [carrier], meta, violations: [] };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// McpCarrierAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * CarrierAdapter implementation for MCP _meta format.\n */\nexport class McpCarrierAdapter implements CarrierAdapter<McpResultLike, McpResultLike> {\n extract(input: McpResultLike): { receipts: PeacEvidenceCarrier[]; meta: CarrierMeta } | null {\n return extractReceiptFromMeta(input);\n }\n\n attach(\n output: McpResultLike,\n carriers: PeacEvidenceCarrier[],\n meta?: CarrierMeta\n ): McpResultLike {\n // Attach first carrier (MCP typically carries one receipt per response)\n if (carriers.length > 0) {\n attachReceiptToMeta(output, carriers[0]);\n }\n return output;\n }\n\n validateConstraints(carrier: PeacEvidenceCarrier, meta: CarrierMeta): CarrierValidationResult {\n return validateCarrierConstraints(carrier, meta);\n }\n}\n","/**\n * MCP _meta reserved key guard.\n *\n * Per MCP specification (2025-11-25), the reserved prefix rule is:\n * \"Any prefix where the second label is `modelcontextprotocol` or `mcp`\n * is reserved.\"\n *\n * The prefix is the segment before the first `/`, split by `.` into labels.\n * Only the second label (labels[1], 0-indexed) determines reservation.\n *\n * Examples:\n * \"dev.mcp/anything\" -> RESERVED (2nd label = mcp)\n * \"io.modelcontextprotocol/data\" -> RESERVED (2nd label = modelcontextprotocol)\n * \"com.mcp.tools/data\" -> RESERVED (2nd label = mcp)\n * \"tools.mcp.com/data\" -> RESERVED (2nd label = mcp)\n * \"mcp.dev/anything\" -> NOT reserved (2nd label = dev)\n * \"modelcontextprotocol.io/data\" -> NOT reserved (2nd label = io)\n * \"com.example.mcp/data\" -> NOT reserved (2nd label = example)\n * \"org.peacprotocol/receipt_ref\" -> NOT reserved (2nd label = peacprotocol)\n */\n\nconst MCP_RESERVED_SECOND_LABELS = ['modelcontextprotocol', 'mcp'];\n\n/**\n * Assert that a _meta key does not use an MCP-reserved prefix.\n *\n * A prefix is reserved when its second label (labels[1], 0-indexed)\n * equals \"mcp\" or \"modelcontextprotocol\" (case-insensitive).\n *\n * @throws Error if the key uses a reserved prefix\n */\nexport function assertNotMcpReservedKey(key: string): void {\n const slashIndex = key.indexOf('/');\n if (slashIndex === -1) return; // No prefix = not reserved\n\n const prefix = key.substring(0, slashIndex);\n const labels = prefix.split('.');\n\n if (labels.length < 2) return; // Single label = no second label = not reserved\n\n if (MCP_RESERVED_SECOND_LABELS.includes(labels[1].toLowerCase())) {\n throw new Error(\n `Reserved MCP _meta key prefix: ${key} (second label \"${labels[1]}\" is reserved per MCP spec)`\n );\n }\n}\n\n/**\n * Check if a _meta key uses an MCP-reserved prefix (non-throwing).\n */\nexport function isMcpReservedKey(key: string): boolean {\n try {\n assertNotMcpReservedKey(key);\n return false;\n } catch {\n return true;\n }\n}\n","/**\n * @peac/mappings-mcp\n *\n * Model Context Protocol (MCP) integration for PEAC.\n * Attach and extract PEAC evidence carriers via MCP _meta keys (DD-125).\n */\n\n// Budget enforcement\nexport * from './budget';\n\n// Carrier _meta format (v0.11.1+ Evidence Carrier Contract)\nexport type {\n McpMeta,\n McpResultLike,\n AttachMetaOptions,\n McpExtractResult,\n McpExtractAsyncResult,\n} from './meta';\n\nexport {\n attachReceiptToMeta,\n extractReceiptFromMeta,\n extractReceiptFromMetaAsync,\n McpCarrierAdapter,\n META_KEY_RECEIPT_REF,\n META_KEY_RECEIPT_JWS,\n META_KEY_RECEIPT_URL,\n META_KEY_AGENT_ID,\n META_KEY_VERIFIED_AT,\n META_KEY_LEGACY_RECEIPT,\n MCP_MAX_CARRIER_SIZE,\n} from './meta';\n\n// MCP _meta reserved key guard\nexport { assertNotMcpReservedKey, isMcpReservedKey } from './guard';\n\n// ---------------------------------------------------------------------------\n// Legacy API (backward compatible)\n// ---------------------------------------------------------------------------\n\n/**\n * MCP Tool Response\n */\nexport interface MCPToolResponse {\n tool: string;\n result: unknown;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * MCP Tool Response with PEAC receipt (legacy format)\n */\nexport interface MCPToolResponseWithReceipt extends MCPToolResponse {\n peac_receipt?: string;\n}\n\n/**\n * Attach PEAC receipt to MCP tool response (legacy format).\n *\n * Uses `peac_receipt` top-level key. For new integrations, prefer\n * `attachReceiptToMeta()` which uses the _meta carrier format (DD-125).\n *\n * @param response - MCP tool response\n * @param receiptJWS - PEAC receipt JWS\n * @returns MCP tool response with PEAC receipt attached\n */\nexport function attachReceipt(\n response: MCPToolResponse,\n receiptJWS: string\n): MCPToolResponseWithReceipt {\n return {\n ...response,\n peac_receipt: receiptJWS,\n };\n}\n\n/**\n * Extract PEAC receipt from MCP tool response.\n *\n * Reads BOTH legacy `peac_receipt` field AND `_meta` carrier format (DD-125).\n * Prefers _meta format when both are present.\n *\n * @param response - MCP tool response (possibly with receipt)\n * @returns PEAC receipt JWS or null if not present\n */\nexport function extractReceipt(response: MCPToolResponseWithReceipt): string | null {\n // 1. Try _meta carrier format (v0.11.1+)\n if (response._meta) {\n const meta = response._meta as Record<string, unknown>;\n // New format: receipt_jws key\n const jws = meta['org.peacprotocol/receipt_jws'];\n if (typeof jws === 'string' && jws.length > 0) {\n return jws;\n }\n // Legacy _meta format: receipt key (v0.10.13)\n const legacyJws = meta['org.peacprotocol/receipt'];\n if (typeof legacyJws === 'string' && legacyJws.length > 0) {\n return legacyJws;\n }\n }\n\n // 2. Fall back to legacy peac_receipt field\n if (typeof response.peac_receipt === 'string' && response.peac_receipt.length > 0) {\n return response.peac_receipt;\n }\n return null;\n}\n\n/**\n * Check if MCP tool response has a PEAC receipt\n *\n * @param response - MCP tool response\n * @returns true if receipt is present\n */\nexport function hasReceipt(response: MCPToolResponseWithReceipt): boolean {\n return extractReceipt(response) !== null;\n}\n\n/**\n * Create MCP tool response with PEAC receipt for paid API calls\n *\n * @param tool - Tool name\n * @param result - Tool execution result\n * @param receiptJWS - PEAC receipt JWS\n * @param metadata - Optional metadata\n * @returns MCP tool response with receipt\n */\nexport function createPaidToolResponse(\n tool: string,\n result: unknown,\n receiptJWS: string,\n metadata?: Record<string, unknown>\n): MCPToolResponseWithReceipt {\n const response: MCPToolResponse = {\n tool,\n result,\n ...(metadata && { metadata }),\n };\n\n return attachReceipt(response, receiptJWS);\n}\n"]}
1
+ {"version":3,"sources":["../src/budget.ts","../src/meta.ts","../src/guard.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["/**\n * Budget enforcement utilities for MCP tool calls\n * Uses bigint for all currency calculations to avoid floating-point errors\n */\n\nexport interface BudgetConfig {\n /** Maximum cost per single call in minor currency units (e.g., cents for USD) */\n maxPerCallMinor?: bigint;\n /** Maximum total cost per day in minor currency units */\n maxDailyMinor?: bigint;\n /** Maximum total cost per month in minor currency units */\n maxMonthlyMinor?: bigint;\n /** Currency code (must match at runtime, e.g., 'USD', 'INR') */\n currency: string;\n}\n\nexport interface BudgetResult {\n /** Whether the cost is allowed within budget limits */\n allowed: boolean;\n /**\n * Remaining budget in minor units (after this operation).\n * - When allowed: the minimum remaining across all applicable limits\n * - When denied: 0n (never negative)\n * - When unbounded: undefined (check `unbounded` flag instead)\n */\n remainingMinor?: bigint;\n /**\n * True when no budget limits are configured.\n * In this case, remainingMinor is undefined.\n */\n unbounded?: boolean;\n /** Error code if not allowed */\n code?: 'budget_exceeded' | 'currency_mismatch';\n /** Human-readable reason if not allowed */\n reason?: string;\n}\n\n/**\n * Check if a cost is within budget.\n * Pure, deterministic function - caller tracks time windows externally.\n *\n * @param spentMinor - Amount already spent in minor units (e.g., cents)\n * @param costMinor - Cost of current operation in minor units\n * @param currency - Currency code (must match config.currency)\n * @param config - Budget configuration\n * @returns Result indicating whether cost is allowed and remaining budget\n *\n * @example\n * ```typescript\n * const config: BudgetConfig = {\n * maxPerCallMinor: 500n, // $5.00 max per call\n * maxDailyMinor: 10000n, // $100.00 max per day\n * currency: 'USD'\n * };\n *\n * const result = checkBudget(\n * 8500n, // Already spent $85.00 today\n * 1000n, // Current call costs $10.00\n * 'USD',\n * config\n * );\n *\n * if (result.allowed) {\n * console.log(`Allowed. Remaining: ${result.remainingMinor} cents`);\n * } else {\n * console.log(`Denied: ${result.reason}`);\n * }\n * ```\n */\nexport function checkBudget(\n spentMinor: bigint,\n costMinor: bigint,\n currency: string,\n config: BudgetConfig\n): BudgetResult {\n // Currency mismatch check\n if (currency !== config.currency) {\n return {\n allowed: false,\n remainingMinor: 0n,\n code: 'currency_mismatch',\n reason: `Currency mismatch: expected ${config.currency}, got ${currency}`,\n };\n }\n\n // Check per-call limit\n if (config.maxPerCallMinor !== undefined && costMinor > config.maxPerCallMinor) {\n return {\n allowed: false,\n remainingMinor: 0n, // Never negative - clamp to 0\n code: 'budget_exceeded',\n reason: `Per-call limit exceeded: cost ${costMinor} > limit ${config.maxPerCallMinor}`,\n };\n }\n\n // Check daily limit (if configured)\n if (config.maxDailyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxDailyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxDailyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Daily limit exceeded: total ${newTotal} > limit ${config.maxDailyMinor}`,\n };\n }\n }\n\n // Check monthly limit (if configured)\n if (config.maxMonthlyMinor !== undefined) {\n const newTotal = spentMinor + costMinor;\n if (newTotal > config.maxMonthlyMinor) {\n return {\n allowed: false,\n remainingMinor: config.maxMonthlyMinor - spentMinor,\n code: 'budget_exceeded',\n reason: `Monthly limit exceeded: total ${newTotal} > limit ${config.maxMonthlyMinor}`,\n };\n }\n }\n\n // Calculate remaining budget (how much can be spent in future operations)\n // This is the minimum of:\n // 1. Per-call limit (max single operation)\n // 2. Remaining daily budget\n // 3. Remaining monthly budget\n const remainingCandidates: bigint[] = [];\n\n if (config.maxPerCallMinor !== undefined) {\n remainingCandidates.push(config.maxPerCallMinor);\n }\n\n if (config.maxDailyMinor !== undefined) {\n const dailyRemaining = config.maxDailyMinor - (spentMinor + costMinor);\n remainingCandidates.push(dailyRemaining);\n }\n\n if (config.maxMonthlyMinor !== undefined) {\n const monthlyRemaining = config.maxMonthlyMinor - (spentMinor + costMinor);\n remainingCandidates.push(monthlyRemaining);\n }\n\n // Return the most restrictive limit\n if (remainingCandidates.length === 0) {\n // No limits configured - unbounded\n return {\n allowed: true,\n unbounded: true,\n };\n }\n\n const remainingMinor = remainingCandidates.reduce((min, val) => (val < min ? val : min));\n\n return {\n allowed: true,\n remainingMinor,\n };\n}\n","/**\n * MCP _meta carrier format.\n *\n * Attach and extract PEAC evidence carriers using MCP _meta keys.\n * Uses reverse-DNS keys under \"org.peacprotocol/\" prefix.\n *\n * New format (v0.11.1+):\n * _meta[\"org.peacprotocol/receipt_ref\"] = \"sha256:...\"\n * _meta[\"org.peacprotocol/receipt_jws\"] = \"eyJ...\"\n *\n * Legacy format (v0.10.13):\n * _meta[\"org.peacprotocol/receipt\"] = \"eyJ...\" (JWS only, no receipt_ref)\n */\n\nimport type {\n PeacEvidenceCarrier,\n CarrierMeta,\n CarrierValidationResult,\n CarrierAdapter,\n} from '@peac/kernel';\nimport {\n PeacEvidenceCarrierSchema,\n computeReceiptRef,\n validateCarrierConstraints,\n verifyReceiptRefConsistency,\n CARRIER_TRANSPORT_LIMITS,\n} from '@peac/schema';\n\n// ---------------------------------------------------------------------------\n// Constants\n// ---------------------------------------------------------------------------\n\n/** _meta key for receipt reference (v0.11.1+) */\nexport const META_KEY_RECEIPT_REF = 'org.peacprotocol/receipt_ref' as const;\n\n/** _meta key for receipt JWS (v0.11.1+) */\nexport const META_KEY_RECEIPT_JWS = 'org.peacprotocol/receipt_jws' as const;\n\n/** _meta key for agent ID (v0.10.13+, unchanged) */\nexport const META_KEY_AGENT_ID = 'org.peacprotocol/agent_id' as const;\n\n/** _meta key for verification timestamp (v0.10.13+, unchanged) */\nexport const META_KEY_VERIFIED_AT = 'org.peacprotocol/verified_at' as const;\n\n/** _meta key for receipt URL locator hint (v0.11.2+) */\nexport const META_KEY_RECEIPT_URL = 'org.peacprotocol/receipt_url' as const;\n\n/** Legacy _meta key for receipt JWS (v0.10.13) */\nexport const META_KEY_LEGACY_RECEIPT = 'org.peacprotocol/receipt' as const;\n\n/** Maximum carrier size for MCP _meta (64 KB) */\nexport const MCP_MAX_CARRIER_SIZE = CARRIER_TRANSPORT_LIMITS.mcp;\n\n// ---------------------------------------------------------------------------\n// Types\n// ---------------------------------------------------------------------------\n\n/** MCP _meta object */\nexport type McpMeta = Record<string, unknown>;\n\n/** MCP JSON-RPC result with _meta */\nexport interface McpResultLike {\n _meta?: McpMeta;\n [key: string]: unknown;\n}\n\n/** Options for attachReceiptToMeta */\nexport interface AttachMetaOptions {\n /** Use legacy format (v0.10.13 peac_receipt key). Default: false */\n legacyFormat?: boolean;\n /** Agent ID to include in _meta */\n agentId?: string;\n /** Verification timestamp (ISO 8601) */\n verifiedAt?: string;\n}\n\n/** Result of extraction */\nexport interface McpExtractResult {\n receipts: PeacEvidenceCarrier[];\n meta: CarrierMeta;\n}\n\n/** Async extraction result with consistency violations */\nexport interface McpExtractAsyncResult extends McpExtractResult {\n violations: string[];\n}\n\n// ---------------------------------------------------------------------------\n// Attach\n// ---------------------------------------------------------------------------\n\n/**\n * Attach PEAC evidence carrier to MCP _meta.\n *\n * Default format (v0.11.1+): writes receipt_ref and receipt_jws as separate keys.\n * Legacy format (opts.legacyFormat): writes single \"receipt\" key (phase 1).\n */\nexport function attachReceiptToMeta(\n result: McpResultLike,\n carrier: PeacEvidenceCarrier,\n opts?: AttachMetaOptions\n): McpResultLike {\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n const validation = validateCarrierConstraints(carrier, meta);\n if (!validation.valid) {\n throw new Error(`Carrier constraint violation: ${validation.violations.join('; ')}`);\n }\n\n if (!result._meta) {\n result._meta = {};\n }\n\n if (opts?.legacyFormat) {\n // legacy format: single JWS string\n if (carrier.receipt_jws) {\n result._meta[META_KEY_LEGACY_RECEIPT] = carrier.receipt_jws;\n }\n } else {\n // v0.11.1+ carrier format\n result._meta[META_KEY_RECEIPT_REF] = carrier.receipt_ref;\n if (carrier.receipt_jws) {\n result._meta[META_KEY_RECEIPT_JWS] = carrier.receipt_jws;\n }\n if (carrier.receipt_url) {\n result._meta[META_KEY_RECEIPT_URL] = carrier.receipt_url;\n }\n }\n\n // Optional metadata fields (unchanged from v0.10.13)\n if (opts?.agentId) {\n result._meta[META_KEY_AGENT_ID] = opts.agentId;\n }\n if (opts?.verifiedAt) {\n result._meta[META_KEY_VERIFIED_AT] = opts.verifiedAt;\n }\n\n return result;\n}\n\n// ---------------------------------------------------------------------------\n// Extract (sync: structural validation only)\n// ---------------------------------------------------------------------------\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (sync).\n *\n * Reads in order:\n * 1. New carrier keys (receipt_ref + receipt_jws)\n * 2. Legacy key (org.peacprotocol/receipt, v0.10.13)\n *\n * For legacy format, computes receipt_ref from the JWS to return a proper\n * PeacEvidenceCarrier (Polish B). Note: this requires async for the hash,\n * so the sync version uses a placeholder receipt_ref for legacy and marks\n * it in the meta. Use extractReceiptFromMetaAsync for full validation.\n */\nexport function extractReceiptFromMeta(result: McpResultLike): McpExtractResult | null {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n return { receipts: [parsed.data as PeacEvidenceCarrier], meta };\n }\n }\n\n // 2. Try legacy format (v0.10.13 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Legacy format has JWS only; we can't compute receipt_ref synchronously.\n // Return the JWS in a carrier with a placeholder ref that extractAsync will fix.\n // For sync extraction, we skip schema validation of receipt_ref since we can't\n // compute it without async. Return the raw data and let async handle integrity.\n return {\n receipts: [\n {\n receipt_ref:\n 'sha256:0000000000000000000000000000000000000000000000000000000000000000' as PeacEvidenceCarrier['receipt_ref'],\n receipt_jws: legacyReceipt,\n },\n ],\n meta: { ...meta, redaction: ['legacy_receipt_ref_pending'] },\n };\n }\n\n return null;\n}\n\n/**\n * Extract PEAC evidence carrier from MCP _meta (async).\n *\n * Performs structural validation AND receipt_ref consistency check.\n * For legacy format (v0.10.13), computes receipt_ref from JWS (Polish B).\n */\nexport async function extractReceiptFromMetaAsync(\n result: McpResultLike\n): Promise<McpExtractAsyncResult | null> {\n if (!result._meta) return null;\n\n const meta: CarrierMeta = {\n transport: 'mcp',\n format: 'embed',\n max_size: MCP_MAX_CARRIER_SIZE,\n };\n\n // 1. Try new format (v0.11.1+)\n const receiptRef = result._meta[META_KEY_RECEIPT_REF];\n if (typeof receiptRef === 'string') {\n const carrier: Record<string, unknown> = { receipt_ref: receiptRef };\n const receiptJws = result._meta[META_KEY_RECEIPT_JWS];\n if (typeof receiptJws === 'string') {\n carrier.receipt_jws = receiptJws;\n }\n const receiptUrl = result._meta[META_KEY_RECEIPT_URL];\n if (typeof receiptUrl === 'string') {\n carrier.receipt_url = receiptUrl;\n }\n\n const parsed = PeacEvidenceCarrierSchema.safeParse(carrier);\n if (parsed.success) {\n const validCarrier = parsed.data as PeacEvidenceCarrier;\n const error = await verifyReceiptRefConsistency(validCarrier);\n const violations = error ? [error] : [];\n return {\n receipts: error ? [] : [validCarrier],\n meta,\n violations,\n };\n }\n }\n\n // 2. Try legacy format (v0.10.13 + Polish B)\n const legacyReceipt = result._meta[META_KEY_LEGACY_RECEIPT];\n if (typeof legacyReceipt === 'string' && legacyReceipt.length > 0) {\n // Compute receipt_ref from legacy JWS\n const computedRef = await computeReceiptRef(legacyReceipt);\n const carrier: PeacEvidenceCarrier = {\n receipt_ref: computedRef,\n receipt_jws: legacyReceipt,\n };\n return { receipts: [carrier], meta, violations: [] };\n }\n\n return null;\n}\n\n// ---------------------------------------------------------------------------\n// McpCarrierAdapter\n// ---------------------------------------------------------------------------\n\n/**\n * CarrierAdapter implementation for MCP _meta format.\n */\nexport class McpCarrierAdapter implements CarrierAdapter<McpResultLike, McpResultLike> {\n extract(input: McpResultLike): { receipts: PeacEvidenceCarrier[]; meta: CarrierMeta } | null {\n return extractReceiptFromMeta(input);\n }\n\n attach(\n output: McpResultLike,\n carriers: PeacEvidenceCarrier[],\n meta?: CarrierMeta\n ): McpResultLike {\n // Attach first carrier (MCP typically carries one receipt per response)\n if (carriers.length > 0) {\n attachReceiptToMeta(output, carriers[0]);\n }\n return output;\n }\n\n validateConstraints(carrier: PeacEvidenceCarrier, meta: CarrierMeta): CarrierValidationResult {\n return validateCarrierConstraints(carrier, meta);\n }\n}\n","/**\n * MCP _meta reserved key guard.\n *\n * Per MCP specification (2025-11-25), the reserved prefix rule is:\n * \"Any prefix where the second label is `modelcontextprotocol` or `mcp`\n * is reserved.\"\n *\n * The prefix is the segment before the first `/`, split by `.` into labels.\n * Only the second label (labels[1], 0-indexed) determines reservation.\n *\n * Examples:\n * \"dev.mcp/anything\" -> RESERVED (2nd label = mcp)\n * \"io.modelcontextprotocol/data\" -> RESERVED (2nd label = modelcontextprotocol)\n * \"com.mcp.tools/data\" -> RESERVED (2nd label = mcp)\n * \"tools.mcp.com/data\" -> RESERVED (2nd label = mcp)\n * \"mcp.dev/anything\" -> NOT reserved (2nd label = dev)\n * \"modelcontextprotocol.io/data\" -> NOT reserved (2nd label = io)\n * \"com.example.mcp/data\" -> NOT reserved (2nd label = example)\n * \"org.peacprotocol/receipt_ref\" -> NOT reserved (2nd label = peacprotocol)\n */\n\nconst MCP_RESERVED_SECOND_LABELS = ['modelcontextprotocol', 'mcp'];\n\n/**\n * Assert that a _meta key does not use an MCP-reserved prefix.\n *\n * A prefix is reserved when its second label (labels[1], 0-indexed)\n * equals \"mcp\" or \"modelcontextprotocol\" (case-insensitive).\n *\n * @throws Error if the key uses a reserved prefix\n */\nexport function assertNotMcpReservedKey(key: string): void {\n const slashIndex = key.indexOf('/');\n if (slashIndex === -1) return; // No prefix = not reserved\n\n const prefix = key.substring(0, slashIndex);\n const labels = prefix.split('.');\n\n if (labels.length < 2) return; // Single label = no second label = not reserved\n\n if (MCP_RESERVED_SECOND_LABELS.includes(labels[1].toLowerCase())) {\n throw new Error(\n `Reserved MCP _meta key prefix: ${key} (second label \"${labels[1]}\" is reserved per MCP spec)`\n );\n }\n}\n\n/**\n * Check if a _meta key uses an MCP-reserved prefix (non-throwing).\n */\nexport function isMcpReservedKey(key: string): boolean {\n try {\n assertNotMcpReservedKey(key);\n return false;\n } catch {\n return true;\n }\n}\n","/**\n * @peac/mappings-mcp\n *\n * Model Context Protocol (MCP) integration for PEAC.\n * Attach and extract PEAC evidence carriers via MCP _meta keys.\n */\n\n// Budget enforcement\nexport * from './budget';\n\n// Carrier _meta format (v0.11.1+ Evidence Carrier Contract)\nexport type {\n McpMeta,\n McpResultLike,\n AttachMetaOptions,\n McpExtractResult,\n McpExtractAsyncResult,\n} from './meta';\n\nexport {\n attachReceiptToMeta,\n extractReceiptFromMeta,\n extractReceiptFromMetaAsync,\n McpCarrierAdapter,\n META_KEY_RECEIPT_REF,\n META_KEY_RECEIPT_JWS,\n META_KEY_RECEIPT_URL,\n META_KEY_AGENT_ID,\n META_KEY_VERIFIED_AT,\n META_KEY_LEGACY_RECEIPT,\n MCP_MAX_CARRIER_SIZE,\n} from './meta';\n\n// MCP _meta reserved key guard\nexport { assertNotMcpReservedKey, isMcpReservedKey } from './guard';\n\n// ---------------------------------------------------------------------------\n// Legacy API (backward compatible)\n// ---------------------------------------------------------------------------\n\n/**\n * MCP Tool Response\n */\nexport interface MCPToolResponse {\n tool: string;\n result: unknown;\n metadata?: Record<string, unknown>;\n [key: string]: unknown;\n}\n\n/**\n * MCP Tool Response with PEAC receipt (legacy format)\n */\nexport interface MCPToolResponseWithReceipt extends MCPToolResponse {\n peac_receipt?: string;\n}\n\n/**\n * Attach PEAC receipt to MCP tool response (legacy format).\n *\n * Uses `peac_receipt` top-level key. For new integrations, prefer\n * `attachReceiptToMeta()` which uses the _meta carrier format.\n *\n * @param response - MCP tool response\n * @param receiptJWS - PEAC receipt JWS\n * @returns MCP tool response with PEAC receipt attached\n */\nexport function attachReceipt(\n response: MCPToolResponse,\n receiptJWS: string\n): MCPToolResponseWithReceipt {\n return {\n ...response,\n peac_receipt: receiptJWS,\n };\n}\n\n/**\n * Extract PEAC receipt from MCP tool response.\n *\n * Reads BOTH legacy `peac_receipt` field AND `_meta` carrier format.\n * Prefers _meta format when both are present.\n *\n * @param response - MCP tool response (possibly with receipt)\n * @returns PEAC receipt JWS or null if not present\n */\nexport function extractReceipt(response: MCPToolResponseWithReceipt): string | null {\n // 1. Try _meta carrier format (v0.11.1+)\n if (response._meta) {\n const meta = response._meta as Record<string, unknown>;\n // New format: receipt_jws key\n const jws = meta['org.peacprotocol/receipt_jws'];\n if (typeof jws === 'string' && jws.length > 0) {\n return jws;\n }\n // Legacy _meta format: receipt key (v0.10.13)\n const legacyJws = meta['org.peacprotocol/receipt'];\n if (typeof legacyJws === 'string' && legacyJws.length > 0) {\n return legacyJws;\n }\n }\n\n // 2. Fall back to legacy peac_receipt field\n if (typeof response.peac_receipt === 'string' && response.peac_receipt.length > 0) {\n return response.peac_receipt;\n }\n return null;\n}\n\n/**\n * Check if MCP tool response has a PEAC receipt\n *\n * @param response - MCP tool response\n * @returns true if receipt is present\n */\nexport function hasReceipt(response: MCPToolResponseWithReceipt): boolean {\n return extractReceipt(response) !== null;\n}\n\n/**\n * Create MCP tool response with PEAC receipt for paid API calls\n *\n * @param tool - Tool name\n * @param result - Tool execution result\n * @param receiptJWS - PEAC receipt JWS\n * @param metadata - Optional metadata\n * @returns MCP tool response with receipt\n */\nexport function createPaidToolResponse(\n tool: string,\n result: unknown,\n receiptJWS: string,\n metadata?: Record<string, unknown>\n): MCPToolResponseWithReceipt {\n const response: MCPToolResponse = {\n tool,\n result,\n ...(metadata && { metadata }),\n };\n\n return attachReceipt(response, receiptJWS);\n}\n"]}
package/dist/meta.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  /**
2
- * MCP _meta carrier format (DD-125).
2
+ * MCP _meta carrier format.
3
3
  *
4
4
  * Attach and extract PEAC evidence carriers using MCP _meta keys.
5
5
  * Uses reverse-DNS keys under "org.peacprotocol/" prefix.
@@ -20,11 +20,11 @@ export declare const META_KEY_RECEIPT_JWS: "org.peacprotocol/receipt_jws";
20
20
  export declare const META_KEY_AGENT_ID: "org.peacprotocol/agent_id";
21
21
  /** _meta key for verification timestamp (v0.10.13+, unchanged) */
22
22
  export declare const META_KEY_VERIFIED_AT: "org.peacprotocol/verified_at";
23
- /** _meta key for receipt URL locator hint (v0.11.2+, DD-135) */
23
+ /** _meta key for receipt URL locator hint (v0.11.2+) */
24
24
  export declare const META_KEY_RECEIPT_URL: "org.peacprotocol/receipt_url";
25
- /** Legacy _meta key for receipt JWS (v0.10.13, DD-125) */
25
+ /** Legacy _meta key for receipt JWS (v0.10.13) */
26
26
  export declare const META_KEY_LEGACY_RECEIPT: "org.peacprotocol/receipt";
27
- /** Maximum carrier size for MCP _meta (64 KB, DD-127) */
27
+ /** Maximum carrier size for MCP _meta (64 KB) */
28
28
  export declare const MCP_MAX_CARRIER_SIZE: 65536;
29
29
  /** MCP _meta object */
30
30
  export type McpMeta = Record<string, unknown>;
@@ -55,13 +55,13 @@ export interface McpExtractAsyncResult extends McpExtractResult {
55
55
  * Attach PEAC evidence carrier to MCP _meta.
56
56
  *
57
57
  * Default format (v0.11.1+): writes receipt_ref and receipt_jws as separate keys.
58
- * Legacy format (opts.legacyFormat): writes single "receipt" key (DD-125 phase 1).
58
+ * Legacy format (opts.legacyFormat): writes single "receipt" key (phase 1).
59
59
  */
60
60
  export declare function attachReceiptToMeta(result: McpResultLike, carrier: PeacEvidenceCarrier, opts?: AttachMetaOptions): McpResultLike;
61
61
  /**
62
62
  * Extract PEAC evidence carrier from MCP _meta (sync).
63
63
  *
64
- * Reads in order (DD-125):
64
+ * Reads in order:
65
65
  * 1. New carrier keys (receipt_ref + receipt_jws)
66
66
  * 2. Legacy key (org.peacprotocol/receipt, v0.10.13)
67
67
  *
@@ -72,7 +72,7 @@ export declare function attachReceiptToMeta(result: McpResultLike, carrier: Peac
72
72
  */
73
73
  export declare function extractReceiptFromMeta(result: McpResultLike): McpExtractResult | null;
74
74
  /**
75
- * Extract PEAC evidence carrier from MCP _meta (async, DD-129).
75
+ * Extract PEAC evidence carrier from MCP _meta (async).
76
76
  *
77
77
  * Performs structural validation AND receipt_ref consistency check.
78
78
  * For legacy format (v0.10.13), computes receipt_ref from JWS (Polish B).
@@ -1 +1 @@
1
- {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACX,uBAAuB,EACvB,cAAc,EACf,MAAM,cAAc,CAAC;AAatB,iDAAiD;AACjD,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,EAAG,2BAAoC,CAAC;AAEtE,kEAAkE;AAClE,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,gEAAgE;AAChE,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,0DAA0D;AAC1D,eAAO,MAAM,uBAAuB,EAAG,0BAAmC,CAAC;AAE3E,yDAAyD;AACzD,eAAO,MAAM,oBAAoB,OAA+B,CAAC;AAMjE,uBAAuB;AACvB,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,2BAA2B;AAC3B,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,mBAAmB,EAC5B,IAAI,CAAC,EAAE,iBAAiB,GACvB,aAAa,CAyCf;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAgDrF;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAgDvC;AAMD;;GAEG;AACH,qBAAa,iBAAkB,YAAW,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC;IACpF,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG;QAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI;IAI5F,MAAM,CACJ,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,IAAI,CAAC,EAAE,WAAW,GACjB,aAAa;IAQhB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,WAAW,GAAG,uBAAuB;CAG9F"}
1
+ {"version":3,"file":"meta.d.ts","sourceRoot":"","sources":["../src/meta.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;GAYG;AAEH,OAAO,KAAK,EACV,mBAAmB,EACnB,WAAW,EACX,uBAAuB,EACvB,cAAc,EACf,MAAM,cAAc,CAAC;AAatB,iDAAiD;AACjD,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,2CAA2C;AAC3C,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,oDAAoD;AACpD,eAAO,MAAM,iBAAiB,EAAG,2BAAoC,CAAC;AAEtE,kEAAkE;AAClE,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,wDAAwD;AACxD,eAAO,MAAM,oBAAoB,EAAG,8BAAuC,CAAC;AAE5E,kDAAkD;AAClD,eAAO,MAAM,uBAAuB,EAAG,0BAAmC,CAAC;AAE3E,iDAAiD;AACjD,eAAO,MAAM,oBAAoB,OAA+B,CAAC;AAMjE,uBAAuB;AACvB,MAAM,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;AAE9C,qCAAqC;AACrC,MAAM,WAAW,aAAa;IAC5B,KAAK,CAAC,EAAE,OAAO,CAAC;IAChB,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC;CACxB;AAED,sCAAsC;AACtC,MAAM,WAAW,iBAAiB;IAChC,oEAAoE;IACpE,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,mCAAmC;IACnC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,wCAAwC;IACxC,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,2BAA2B;AAC3B,MAAM,WAAW,gBAAgB;IAC/B,QAAQ,EAAE,mBAAmB,EAAE,CAAC;IAChC,IAAI,EAAE,WAAW,CAAC;CACnB;AAED,0DAA0D;AAC1D,MAAM,WAAW,qBAAsB,SAAQ,gBAAgB;IAC7D,UAAU,EAAE,MAAM,EAAE,CAAC;CACtB;AAMD;;;;;GAKG;AACH,wBAAgB,mBAAmB,CACjC,MAAM,EAAE,aAAa,EACrB,OAAO,EAAE,mBAAmB,EAC5B,IAAI,CAAC,EAAE,iBAAiB,GACvB,aAAa,CAyCf;AAMD;;;;;;;;;;;GAWG;AACH,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,aAAa,GAAG,gBAAgB,GAAG,IAAI,CAgDrF;AAED;;;;;GAKG;AACH,wBAAsB,2BAA2B,CAC/C,MAAM,EAAE,aAAa,GACpB,OAAO,CAAC,qBAAqB,GAAG,IAAI,CAAC,CAgDvC;AAMD;;GAEG;AACH,qBAAa,iBAAkB,YAAW,cAAc,CAAC,aAAa,EAAE,aAAa,CAAC;IACpF,OAAO,CAAC,KAAK,EAAE,aAAa,GAAG;QAAE,QAAQ,EAAE,mBAAmB,EAAE,CAAC;QAAC,IAAI,EAAE,WAAW,CAAA;KAAE,GAAG,IAAI;IAI5F,MAAM,CACJ,MAAM,EAAE,aAAa,EACrB,QAAQ,EAAE,mBAAmB,EAAE,EAC/B,IAAI,CAAC,EAAE,WAAW,GACjB,aAAa;IAQhB,mBAAmB,CAAC,OAAO,EAAE,mBAAmB,EAAE,IAAI,EAAE,WAAW,GAAG,uBAAuB;CAG9F"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@peac/mappings-mcp",
3
- "version": "0.12.0",
3
+ "version": "0.12.2",
4
4
  "description": "Model Context Protocol (MCP) integration for PEAC",
5
5
  "main": "dist/index.cjs",
6
6
  "types": "dist/index.d.ts",
@@ -23,8 +23,8 @@
23
23
  "access": "public"
24
24
  },
25
25
  "dependencies": {
26
- "@peac/kernel": "0.12.0",
27
- "@peac/schema": "0.12.0"
26
+ "@peac/kernel": "0.12.2",
27
+ "@peac/schema": "0.12.2"
28
28
  },
29
29
  "devDependencies": {
30
30
  "@types/node": "^22.19.11",