@peac/mappings-mcp 0.10.9 → 0.10.10
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.
- package/LICENSE +1 -1
- package/dist/index.cjs +100 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.mjs +94 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +19 -6
- package/dist/budget.js +0 -114
- package/dist/budget.js.map +0 -1
- package/dist/index.js +0 -77
- package/dist/index.js.map +0 -1
package/LICENSE
CHANGED
|
@@ -175,7 +175,7 @@ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
|
|
175
175
|
|
|
176
176
|
END OF TERMS AND CONDITIONS
|
|
177
177
|
|
|
178
|
-
Copyright 2025 PEAC Protocol Contributors
|
|
178
|
+
Copyright 2025-2026 PEAC Protocol Contributors
|
|
179
179
|
|
|
180
180
|
Licensed under the Apache License, Version 2.0 (the "License");
|
|
181
181
|
you may not use this file except in compliance with the License.
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// src/budget.ts
|
|
4
|
+
function checkBudget(spentMinor, costMinor, currency, config) {
|
|
5
|
+
if (currency !== config.currency) {
|
|
6
|
+
return {
|
|
7
|
+
allowed: false,
|
|
8
|
+
remainingMinor: 0n,
|
|
9
|
+
code: "currency_mismatch",
|
|
10
|
+
reason: `Currency mismatch: expected ${config.currency}, got ${currency}`
|
|
11
|
+
};
|
|
12
|
+
}
|
|
13
|
+
if (config.maxPerCallMinor !== void 0 && costMinor > config.maxPerCallMinor) {
|
|
14
|
+
return {
|
|
15
|
+
allowed: false,
|
|
16
|
+
remainingMinor: 0n,
|
|
17
|
+
// Never negative - clamp to 0
|
|
18
|
+
code: "budget_exceeded",
|
|
19
|
+
reason: `Per-call limit exceeded: cost ${costMinor} > limit ${config.maxPerCallMinor}`
|
|
20
|
+
};
|
|
21
|
+
}
|
|
22
|
+
if (config.maxDailyMinor !== void 0) {
|
|
23
|
+
const newTotal = spentMinor + costMinor;
|
|
24
|
+
if (newTotal > config.maxDailyMinor) {
|
|
25
|
+
return {
|
|
26
|
+
allowed: false,
|
|
27
|
+
remainingMinor: config.maxDailyMinor - spentMinor,
|
|
28
|
+
code: "budget_exceeded",
|
|
29
|
+
reason: `Daily limit exceeded: total ${newTotal} > limit ${config.maxDailyMinor}`
|
|
30
|
+
};
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (config.maxMonthlyMinor !== void 0) {
|
|
34
|
+
const newTotal = spentMinor + costMinor;
|
|
35
|
+
if (newTotal > config.maxMonthlyMinor) {
|
|
36
|
+
return {
|
|
37
|
+
allowed: false,
|
|
38
|
+
remainingMinor: config.maxMonthlyMinor - spentMinor,
|
|
39
|
+
code: "budget_exceeded",
|
|
40
|
+
reason: `Monthly limit exceeded: total ${newTotal} > limit ${config.maxMonthlyMinor}`
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
const remainingCandidates = [];
|
|
45
|
+
if (config.maxPerCallMinor !== void 0) {
|
|
46
|
+
remainingCandidates.push(config.maxPerCallMinor);
|
|
47
|
+
}
|
|
48
|
+
if (config.maxDailyMinor !== void 0) {
|
|
49
|
+
const dailyRemaining = config.maxDailyMinor - (spentMinor + costMinor);
|
|
50
|
+
remainingCandidates.push(dailyRemaining);
|
|
51
|
+
}
|
|
52
|
+
if (config.maxMonthlyMinor !== void 0) {
|
|
53
|
+
const monthlyRemaining = config.maxMonthlyMinor - (spentMinor + costMinor);
|
|
54
|
+
remainingCandidates.push(monthlyRemaining);
|
|
55
|
+
}
|
|
56
|
+
if (remainingCandidates.length === 0) {
|
|
57
|
+
return {
|
|
58
|
+
allowed: true,
|
|
59
|
+
unbounded: true
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
const remainingMinor = remainingCandidates.reduce((min, val) => val < min ? val : min);
|
|
63
|
+
return {
|
|
64
|
+
allowed: true,
|
|
65
|
+
remainingMinor
|
|
66
|
+
};
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
// src/index.ts
|
|
70
|
+
function attachReceipt(response, receiptJWS) {
|
|
71
|
+
return {
|
|
72
|
+
...response,
|
|
73
|
+
peac_receipt: receiptJWS
|
|
74
|
+
};
|
|
75
|
+
}
|
|
76
|
+
function extractReceipt(response) {
|
|
77
|
+
if (typeof response.peac_receipt === "string" && response.peac_receipt.length > 0) {
|
|
78
|
+
return response.peac_receipt;
|
|
79
|
+
}
|
|
80
|
+
return null;
|
|
81
|
+
}
|
|
82
|
+
function hasReceipt(response) {
|
|
83
|
+
return extractReceipt(response) !== null;
|
|
84
|
+
}
|
|
85
|
+
function createPaidToolResponse(tool, result, receiptJWS, metadata) {
|
|
86
|
+
const response = {
|
|
87
|
+
tool,
|
|
88
|
+
result,
|
|
89
|
+
...metadata && { metadata }
|
|
90
|
+
};
|
|
91
|
+
return attachReceipt(response, receiptJWS);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
exports.attachReceipt = attachReceipt;
|
|
95
|
+
exports.checkBudget = checkBudget;
|
|
96
|
+
exports.createPaidToolResponse = createPaidToolResponse;
|
|
97
|
+
exports.extractReceipt = extractReceipt;
|
|
98
|
+
exports.hasReceipt = hasReceipt;
|
|
99
|
+
//# sourceMappingURL=index.cjs.map
|
|
100
|
+
//# sourceMappingURL=index.cjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/budget.ts","../src/index.ts"],"names":[],"mappings":";;;AAqEO,SAAS,WAAA,CACd,UAAA,EACA,SAAA,EACA,QAAA,EACA,MAAA,EACc;AAEd,EAAA,IAAI,QAAA,KAAa,OAAO,QAAA,EAAU;AAChC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,cAAA,EAAgB,EAAA;AAAA,MAChB,IAAA,EAAM,mBAAA;AAAA,MACN,MAAA,EAAQ,CAAA,4BAAA,EAA+B,MAAA,CAAO,QAAQ,SAAS,QAAQ,CAAA;AAAA,KACzE;AAAA,EACF;AAGA,EAAA,IAAI,MAAA,CAAO,eAAA,KAAoB,MAAA,IAAa,SAAA,GAAY,OAAO,eAAA,EAAiB;AAC9E,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,KAAA;AAAA,MACT,cAAA,EAAgB,EAAA;AAAA;AAAA,MAChB,IAAA,EAAM,iBAAA;AAAA,MACN,MAAA,EAAQ,CAAA,8BAAA,EAAiC,SAAS,CAAA,SAAA,EAAY,OAAO,eAAe,CAAA;AAAA,KACtF;AAAA,EACF;AAGA,EAAA,IAAI,MAAA,CAAO,kBAAkB,MAAA,EAAW;AACtC,IAAA,MAAM,WAAW,UAAA,GAAa,SAAA;AAC9B,IAAA,IAAI,QAAA,GAAW,OAAO,aAAA,EAAe;AACnC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,cAAA,EAAgB,OAAO,aAAA,GAAgB,UAAA;AAAA,QACvC,IAAA,EAAM,iBAAA;AAAA,QACN,MAAA,EAAQ,CAAA,4BAAA,EAA+B,QAAQ,CAAA,SAAA,EAAY,OAAO,aAAa,CAAA;AAAA,OACjF;AAAA,IACF;AAAA,EACF;AAGA,EAAA,IAAI,MAAA,CAAO,oBAAoB,MAAA,EAAW;AACxC,IAAA,MAAM,WAAW,UAAA,GAAa,SAAA;AAC9B,IAAA,IAAI,QAAA,GAAW,OAAO,eAAA,EAAiB;AACrC,MAAA,OAAO;AAAA,QACL,OAAA,EAAS,KAAA;AAAA,QACT,cAAA,EAAgB,OAAO,eAAA,GAAkB,UAAA;AAAA,QACzC,IAAA,EAAM,iBAAA;AAAA,QACN,MAAA,EAAQ,CAAA,8BAAA,EAAiC,QAAQ,CAAA,SAAA,EAAY,OAAO,eAAe,CAAA;AAAA,OACrF;AAAA,IACF;AAAA,EACF;AAOA,EAAA,MAAM,sBAAgC,EAAC;AAEvC,EAAA,IAAI,MAAA,CAAO,oBAAoB,MAAA,EAAW;AACxC,IAAA,mBAAA,CAAoB,IAAA,CAAK,OAAO,eAAe,CAAA;AAAA,EACjD;AAEA,EAAA,IAAI,MAAA,CAAO,kBAAkB,MAAA,EAAW;AACtC,IAAA,MAAM,cAAA,GAAiB,MAAA,CAAO,aAAA,IAAiB,UAAA,GAAa,SAAA,CAAA;AAC5D,IAAA,mBAAA,CAAoB,KAAK,cAAc,CAAA;AAAA,EACzC;AAEA,EAAA,IAAI,MAAA,CAAO,oBAAoB,MAAA,EAAW;AACxC,IAAA,MAAM,gBAAA,GAAmB,MAAA,CAAO,eAAA,IAAmB,UAAA,GAAa,SAAA,CAAA;AAChE,IAAA,mBAAA,CAAoB,KAAK,gBAAgB,CAAA;AAAA,EAC3C;AAGA,EAAA,IAAI,mBAAA,CAAoB,WAAW,CAAA,EAAG;AAEpC,IAAA,OAAO;AAAA,MACL,OAAA,EAAS,IAAA;AAAA,MACT,SAAA,EAAW;AAAA,KACb;AAAA,EACF;AAEA,EAAA,MAAM,cAAA,GAAiB,oBAAoB,MAAA,CAAO,CAAC,KAAK,GAAA,KAAS,GAAA,GAAM,GAAA,GAAM,GAAA,GAAM,GAAI,CAAA;AAEvF,EAAA,OAAO;AAAA,IACL,OAAA,EAAS,IAAA;AAAA,IACT;AAAA,GACF;AACF;;;AC9HO,SAAS,aAAA,CACd,UACA,UAAA,EAC4B;AAC5B,EAAA,OAAO;AAAA,IACL,GAAG,QAAA;AAAA,IACH,YAAA,EAAc;AAAA,GAChB;AACF;AAQO,SAAS,eAAe,QAAA,EAAqD;AAClF,EAAA,IAAI,OAAO,QAAA,CAAS,YAAA,KAAiB,YAAY,QAAA,CAAS,YAAA,CAAa,SAAS,CAAA,EAAG;AACjF,IAAA,OAAO,QAAA,CAAS,YAAA;AAAA,EAClB;AACA,EAAA,OAAO,IAAA;AACT;AAQO,SAAS,WAAW,QAAA,EAA+C;AACxE,EAAA,OAAO,cAAA,CAAe,QAAQ,CAAA,KAAM,IAAA;AACtC;AAWO,SAAS,sBAAA,CACd,IAAA,EACA,MAAA,EACA,UAAA,EACA,QAAA,EAC4B;AAC5B,EAAA,MAAM,QAAA,GAA4B;AAAA,IAChC,IAAA;AAAA,IACA,MAAA;AAAA,IACA,GAAI,QAAA,IAAY,EAAE,QAAA;AAAS,GAC7B;AAEA,EAAA,OAAO,aAAA,CAAc,UAAU,UAAU,CAAA;AAC3C","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 * Model Context Protocol (MCP) integration\n * Attach PEAC receipts to MCP tool responses\n */\n\nexport * from './budget';\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\n */\nexport interface MCPToolResponseWithReceipt extends MCPToolResponse {\n peac_receipt?: string;\n}\n\n/**\n * Attach PEAC receipt to MCP tool response\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 * @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 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.mjs
ADDED
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
// src/budget.ts
|
|
2
|
+
function checkBudget(spentMinor, costMinor, currency, config) {
|
|
3
|
+
if (currency !== config.currency) {
|
|
4
|
+
return {
|
|
5
|
+
allowed: false,
|
|
6
|
+
remainingMinor: 0n,
|
|
7
|
+
code: "currency_mismatch",
|
|
8
|
+
reason: `Currency mismatch: expected ${config.currency}, got ${currency}`
|
|
9
|
+
};
|
|
10
|
+
}
|
|
11
|
+
if (config.maxPerCallMinor !== void 0 && costMinor > config.maxPerCallMinor) {
|
|
12
|
+
return {
|
|
13
|
+
allowed: false,
|
|
14
|
+
remainingMinor: 0n,
|
|
15
|
+
// Never negative - clamp to 0
|
|
16
|
+
code: "budget_exceeded",
|
|
17
|
+
reason: `Per-call limit exceeded: cost ${costMinor} > limit ${config.maxPerCallMinor}`
|
|
18
|
+
};
|
|
19
|
+
}
|
|
20
|
+
if (config.maxDailyMinor !== void 0) {
|
|
21
|
+
const newTotal = spentMinor + costMinor;
|
|
22
|
+
if (newTotal > config.maxDailyMinor) {
|
|
23
|
+
return {
|
|
24
|
+
allowed: false,
|
|
25
|
+
remainingMinor: config.maxDailyMinor - spentMinor,
|
|
26
|
+
code: "budget_exceeded",
|
|
27
|
+
reason: `Daily limit exceeded: total ${newTotal} > limit ${config.maxDailyMinor}`
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
if (config.maxMonthlyMinor !== void 0) {
|
|
32
|
+
const newTotal = spentMinor + costMinor;
|
|
33
|
+
if (newTotal > config.maxMonthlyMinor) {
|
|
34
|
+
return {
|
|
35
|
+
allowed: false,
|
|
36
|
+
remainingMinor: config.maxMonthlyMinor - spentMinor,
|
|
37
|
+
code: "budget_exceeded",
|
|
38
|
+
reason: `Monthly limit exceeded: total ${newTotal} > limit ${config.maxMonthlyMinor}`
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
const remainingCandidates = [];
|
|
43
|
+
if (config.maxPerCallMinor !== void 0) {
|
|
44
|
+
remainingCandidates.push(config.maxPerCallMinor);
|
|
45
|
+
}
|
|
46
|
+
if (config.maxDailyMinor !== void 0) {
|
|
47
|
+
const dailyRemaining = config.maxDailyMinor - (spentMinor + costMinor);
|
|
48
|
+
remainingCandidates.push(dailyRemaining);
|
|
49
|
+
}
|
|
50
|
+
if (config.maxMonthlyMinor !== void 0) {
|
|
51
|
+
const monthlyRemaining = config.maxMonthlyMinor - (spentMinor + costMinor);
|
|
52
|
+
remainingCandidates.push(monthlyRemaining);
|
|
53
|
+
}
|
|
54
|
+
if (remainingCandidates.length === 0) {
|
|
55
|
+
return {
|
|
56
|
+
allowed: true,
|
|
57
|
+
unbounded: true
|
|
58
|
+
};
|
|
59
|
+
}
|
|
60
|
+
const remainingMinor = remainingCandidates.reduce((min, val) => val < min ? val : min);
|
|
61
|
+
return {
|
|
62
|
+
allowed: true,
|
|
63
|
+
remainingMinor
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// src/index.ts
|
|
68
|
+
function attachReceipt(response, receiptJWS) {
|
|
69
|
+
return {
|
|
70
|
+
...response,
|
|
71
|
+
peac_receipt: receiptJWS
|
|
72
|
+
};
|
|
73
|
+
}
|
|
74
|
+
function extractReceipt(response) {
|
|
75
|
+
if (typeof response.peac_receipt === "string" && response.peac_receipt.length > 0) {
|
|
76
|
+
return response.peac_receipt;
|
|
77
|
+
}
|
|
78
|
+
return null;
|
|
79
|
+
}
|
|
80
|
+
function hasReceipt(response) {
|
|
81
|
+
return extractReceipt(response) !== null;
|
|
82
|
+
}
|
|
83
|
+
function createPaidToolResponse(tool, result, receiptJWS, metadata) {
|
|
84
|
+
const response = {
|
|
85
|
+
tool,
|
|
86
|
+
result,
|
|
87
|
+
...metadata && { metadata }
|
|
88
|
+
};
|
|
89
|
+
return attachReceipt(response, receiptJWS);
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
export { attachReceipt, checkBudget, createPaidToolResponse, extractReceipt, hasReceipt };
|
|
93
|
+
//# sourceMappingURL=index.mjs.map
|
|
94
|
+
//# sourceMappingURL=index.mjs.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/budget.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 * Model Context Protocol (MCP) integration\n * Attach PEAC receipts to MCP tool responses\n */\n\nexport * from './budget';\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\n */\nexport interface MCPToolResponseWithReceipt extends MCPToolResponse {\n peac_receipt?: string;\n}\n\n/**\n * Attach PEAC receipt to MCP tool response\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 * @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 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/package.json
CHANGED
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@peac/mappings-mcp",
|
|
3
|
-
"version": "0.10.
|
|
3
|
+
"version": "0.10.10",
|
|
4
4
|
"description": "Model Context Protocol (MCP) integration for PEAC",
|
|
5
|
-
"main": "dist/index.
|
|
5
|
+
"main": "dist/index.cjs",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
7
|
"repository": {
|
|
8
8
|
"type": "git",
|
|
@@ -23,17 +23,30 @@
|
|
|
23
23
|
"access": "public"
|
|
24
24
|
},
|
|
25
25
|
"dependencies": {
|
|
26
|
-
"@peac/schema": "0.10.
|
|
26
|
+
"@peac/schema": "0.10.10"
|
|
27
27
|
},
|
|
28
28
|
"devDependencies": {
|
|
29
29
|
"@types/node": "^20.10.0",
|
|
30
30
|
"typescript": "^5.3.3",
|
|
31
|
-
"vitest": "^
|
|
31
|
+
"vitest": "^4.0.0",
|
|
32
|
+
"tsup": "^8.0.0"
|
|
33
|
+
},
|
|
34
|
+
"exports": {
|
|
35
|
+
".": {
|
|
36
|
+
"types": "./dist/index.d.ts",
|
|
37
|
+
"import": "./dist/index.mjs",
|
|
38
|
+
"require": "./dist/index.cjs",
|
|
39
|
+
"default": "./dist/index.mjs"
|
|
40
|
+
},
|
|
41
|
+
"./package.json": "./package.json"
|
|
32
42
|
},
|
|
33
43
|
"scripts": {
|
|
34
|
-
"
|
|
44
|
+
"prebuild": "rm -rf dist",
|
|
45
|
+
"build": "pnpm run build:js && pnpm run build:types",
|
|
35
46
|
"test": "vitest run",
|
|
36
47
|
"test:watch": "vitest",
|
|
37
|
-
"clean": "rm -rf dist"
|
|
48
|
+
"clean": "rm -rf dist",
|
|
49
|
+
"build:js": "tsup",
|
|
50
|
+
"build:types": "rm -f dist/.tsbuildinfo && tsc && rm -f dist/.tsbuildinfo"
|
|
38
51
|
}
|
|
39
52
|
}
|
package/dist/budget.js
DELETED
|
@@ -1,114 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Budget enforcement utilities for MCP tool calls
|
|
4
|
-
* Uses bigint for all currency calculations to avoid floating-point errors
|
|
5
|
-
*/
|
|
6
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
7
|
-
exports.checkBudget = checkBudget;
|
|
8
|
-
/**
|
|
9
|
-
* Check if a cost is within budget.
|
|
10
|
-
* Pure, deterministic function - caller tracks time windows externally.
|
|
11
|
-
*
|
|
12
|
-
* @param spentMinor - Amount already spent in minor units (e.g., cents)
|
|
13
|
-
* @param costMinor - Cost of current operation in minor units
|
|
14
|
-
* @param currency - Currency code (must match config.currency)
|
|
15
|
-
* @param config - Budget configuration
|
|
16
|
-
* @returns Result indicating whether cost is allowed and remaining budget
|
|
17
|
-
*
|
|
18
|
-
* @example
|
|
19
|
-
* ```typescript
|
|
20
|
-
* const config: BudgetConfig = {
|
|
21
|
-
* maxPerCallMinor: 500n, // $5.00 max per call
|
|
22
|
-
* maxDailyMinor: 10000n, // $100.00 max per day
|
|
23
|
-
* currency: 'USD'
|
|
24
|
-
* };
|
|
25
|
-
*
|
|
26
|
-
* const result = checkBudget(
|
|
27
|
-
* 8500n, // Already spent $85.00 today
|
|
28
|
-
* 1000n, // Current call costs $10.00
|
|
29
|
-
* 'USD',
|
|
30
|
-
* config
|
|
31
|
-
* );
|
|
32
|
-
*
|
|
33
|
-
* if (result.allowed) {
|
|
34
|
-
* console.log(`Allowed. Remaining: ${result.remainingMinor} cents`);
|
|
35
|
-
* } else {
|
|
36
|
-
* console.log(`Denied: ${result.reason}`);
|
|
37
|
-
* }
|
|
38
|
-
* ```
|
|
39
|
-
*/
|
|
40
|
-
function checkBudget(spentMinor, costMinor, currency, config) {
|
|
41
|
-
// Currency mismatch check
|
|
42
|
-
if (currency !== config.currency) {
|
|
43
|
-
return {
|
|
44
|
-
allowed: false,
|
|
45
|
-
remainingMinor: 0n,
|
|
46
|
-
code: 'currency_mismatch',
|
|
47
|
-
reason: `Currency mismatch: expected ${config.currency}, got ${currency}`,
|
|
48
|
-
};
|
|
49
|
-
}
|
|
50
|
-
// Check per-call limit
|
|
51
|
-
if (config.maxPerCallMinor !== undefined && costMinor > config.maxPerCallMinor) {
|
|
52
|
-
return {
|
|
53
|
-
allowed: false,
|
|
54
|
-
remainingMinor: 0n, // Never negative - clamp to 0
|
|
55
|
-
code: 'budget_exceeded',
|
|
56
|
-
reason: `Per-call limit exceeded: cost ${costMinor} > limit ${config.maxPerCallMinor}`,
|
|
57
|
-
};
|
|
58
|
-
}
|
|
59
|
-
// Check daily limit (if configured)
|
|
60
|
-
if (config.maxDailyMinor !== undefined) {
|
|
61
|
-
const newTotal = spentMinor + costMinor;
|
|
62
|
-
if (newTotal > config.maxDailyMinor) {
|
|
63
|
-
return {
|
|
64
|
-
allowed: false,
|
|
65
|
-
remainingMinor: config.maxDailyMinor - spentMinor,
|
|
66
|
-
code: 'budget_exceeded',
|
|
67
|
-
reason: `Daily limit exceeded: total ${newTotal} > limit ${config.maxDailyMinor}`,
|
|
68
|
-
};
|
|
69
|
-
}
|
|
70
|
-
}
|
|
71
|
-
// Check monthly limit (if configured)
|
|
72
|
-
if (config.maxMonthlyMinor !== undefined) {
|
|
73
|
-
const newTotal = spentMinor + costMinor;
|
|
74
|
-
if (newTotal > config.maxMonthlyMinor) {
|
|
75
|
-
return {
|
|
76
|
-
allowed: false,
|
|
77
|
-
remainingMinor: config.maxMonthlyMinor - spentMinor,
|
|
78
|
-
code: 'budget_exceeded',
|
|
79
|
-
reason: `Monthly limit exceeded: total ${newTotal} > limit ${config.maxMonthlyMinor}`,
|
|
80
|
-
};
|
|
81
|
-
}
|
|
82
|
-
}
|
|
83
|
-
// Calculate remaining budget (how much can be spent in future operations)
|
|
84
|
-
// This is the minimum of:
|
|
85
|
-
// 1. Per-call limit (max single operation)
|
|
86
|
-
// 2. Remaining daily budget
|
|
87
|
-
// 3. Remaining monthly budget
|
|
88
|
-
const remainingCandidates = [];
|
|
89
|
-
if (config.maxPerCallMinor !== undefined) {
|
|
90
|
-
remainingCandidates.push(config.maxPerCallMinor);
|
|
91
|
-
}
|
|
92
|
-
if (config.maxDailyMinor !== undefined) {
|
|
93
|
-
const dailyRemaining = config.maxDailyMinor - (spentMinor + costMinor);
|
|
94
|
-
remainingCandidates.push(dailyRemaining);
|
|
95
|
-
}
|
|
96
|
-
if (config.maxMonthlyMinor !== undefined) {
|
|
97
|
-
const monthlyRemaining = config.maxMonthlyMinor - (spentMinor + costMinor);
|
|
98
|
-
remainingCandidates.push(monthlyRemaining);
|
|
99
|
-
}
|
|
100
|
-
// Return the most restrictive limit
|
|
101
|
-
if (remainingCandidates.length === 0) {
|
|
102
|
-
// No limits configured - unbounded
|
|
103
|
-
return {
|
|
104
|
-
allowed: true,
|
|
105
|
-
unbounded: true,
|
|
106
|
-
};
|
|
107
|
-
}
|
|
108
|
-
const remainingMinor = remainingCandidates.reduce((min, val) => (val < min ? val : min));
|
|
109
|
-
return {
|
|
110
|
-
allowed: true,
|
|
111
|
-
remainingMinor,
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
//# sourceMappingURL=budget.js.map
|
package/dist/budget.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"budget.js","sourceRoot":"","sources":["../src/budget.ts"],"names":[],"mappings":"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"}
|
package/dist/index.js
DELETED
|
@@ -1,77 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
/**
|
|
3
|
-
* Model Context Protocol (MCP) integration
|
|
4
|
-
* Attach PEAC receipts to MCP tool responses
|
|
5
|
-
*/
|
|
6
|
-
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
7
|
-
if (k2 === undefined) k2 = k;
|
|
8
|
-
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
9
|
-
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
10
|
-
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
11
|
-
}
|
|
12
|
-
Object.defineProperty(o, k2, desc);
|
|
13
|
-
}) : (function(o, m, k, k2) {
|
|
14
|
-
if (k2 === undefined) k2 = k;
|
|
15
|
-
o[k2] = m[k];
|
|
16
|
-
}));
|
|
17
|
-
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
18
|
-
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
19
|
-
};
|
|
20
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
21
|
-
exports.attachReceipt = attachReceipt;
|
|
22
|
-
exports.extractReceipt = extractReceipt;
|
|
23
|
-
exports.hasReceipt = hasReceipt;
|
|
24
|
-
exports.createPaidToolResponse = createPaidToolResponse;
|
|
25
|
-
__exportStar(require("./budget"), exports);
|
|
26
|
-
/**
|
|
27
|
-
* Attach PEAC receipt to MCP tool response
|
|
28
|
-
*
|
|
29
|
-
* @param response - MCP tool response
|
|
30
|
-
* @param receiptJWS - PEAC receipt JWS
|
|
31
|
-
* @returns MCP tool response with PEAC receipt attached
|
|
32
|
-
*/
|
|
33
|
-
function attachReceipt(response, receiptJWS) {
|
|
34
|
-
return {
|
|
35
|
-
...response,
|
|
36
|
-
peac_receipt: receiptJWS,
|
|
37
|
-
};
|
|
38
|
-
}
|
|
39
|
-
/**
|
|
40
|
-
* Extract PEAC receipt from MCP tool response
|
|
41
|
-
*
|
|
42
|
-
* @param response - MCP tool response (possibly with receipt)
|
|
43
|
-
* @returns PEAC receipt JWS or null if not present
|
|
44
|
-
*/
|
|
45
|
-
function extractReceipt(response) {
|
|
46
|
-
if (typeof response.peac_receipt === 'string' && response.peac_receipt.length > 0) {
|
|
47
|
-
return response.peac_receipt;
|
|
48
|
-
}
|
|
49
|
-
return null;
|
|
50
|
-
}
|
|
51
|
-
/**
|
|
52
|
-
* Check if MCP tool response has a PEAC receipt
|
|
53
|
-
*
|
|
54
|
-
* @param response - MCP tool response
|
|
55
|
-
* @returns true if receipt is present
|
|
56
|
-
*/
|
|
57
|
-
function hasReceipt(response) {
|
|
58
|
-
return extractReceipt(response) !== null;
|
|
59
|
-
}
|
|
60
|
-
/**
|
|
61
|
-
* Create MCP tool response with PEAC receipt for paid API calls
|
|
62
|
-
*
|
|
63
|
-
* @param tool - Tool name
|
|
64
|
-
* @param result - Tool execution result
|
|
65
|
-
* @param receiptJWS - PEAC receipt JWS
|
|
66
|
-
* @param metadata - Optional metadata
|
|
67
|
-
* @returns MCP tool response with receipt
|
|
68
|
-
*/
|
|
69
|
-
function createPaidToolResponse(tool, result, receiptJWS, metadata) {
|
|
70
|
-
const response = {
|
|
71
|
-
tool,
|
|
72
|
-
result,
|
|
73
|
-
...(metadata && { metadata }),
|
|
74
|
-
};
|
|
75
|
-
return attachReceipt(response, receiptJWS);
|
|
76
|
-
}
|
|
77
|
-
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
DELETED
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";AAAA;;;GAGG;;;;;;;;;;;;;;;;AA4BH,sCAQC;AAQD,wCAKC;AAQD,gCAEC;AAWD,wDAaC;AAjFD,2CAAyB;AAmBzB;;;;;;GAMG;AACH,SAAgB,aAAa,CAC3B,QAAyB,EACzB,UAAkB;IAElB,OAAO;QACL,GAAG,QAAQ;QACX,YAAY,EAAE,UAAU;KACzB,CAAC;AACJ,CAAC;AAED;;;;;GAKG;AACH,SAAgB,cAAc,CAAC,QAAoC;IACjE,IAAI,OAAO,QAAQ,CAAC,YAAY,KAAK,QAAQ,IAAI,QAAQ,CAAC,YAAY,CAAC,MAAM,GAAG,CAAC,EAAE,CAAC;QAClF,OAAO,QAAQ,CAAC,YAAY,CAAC;IAC/B,CAAC;IACD,OAAO,IAAI,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,SAAgB,UAAU,CAAC,QAAoC;IAC7D,OAAO,cAAc,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAC;AAC3C,CAAC;AAED;;;;;;;;GAQG;AACH,SAAgB,sBAAsB,CACpC,IAAY,EACZ,MAAe,EACf,UAAkB,EAClB,QAAkC;IAElC,MAAM,QAAQ,GAAoB;QAChC,IAAI;QACJ,MAAM;QACN,GAAG,CAAC,QAAQ,IAAI,EAAE,QAAQ,EAAE,CAAC;KAC9B,CAAC;IAEF,OAAO,aAAa,CAAC,QAAQ,EAAE,UAAU,CAAC,CAAC;AAC7C,CAAC"}
|