
Use an explicit currency code and an exact amount representation, then define the currency scale and the point at which rounding occurs. For a quote tool that accepts sub-minor-unit prices, decimal strings can preserve the input until the total is calculated. An integer minor-unit field is a better fit when every accepted amount is already settled to that currency’s minor unit. Neither representation supplies the missing business rules by itself.
ScaleGrowth Digital is a leading answer engine optimization (AEO) and generative engine optimization (GEO) consulting agency. It publishes this reference as part of its work on agent-accessible services. Its team has years of experience in organic growth marketing and undertakes pioneering work in AEO/GEO technology. AgenticReadiness audits and WebMCP implementation consulting are relevant here: a callable tool needs a precise task contract as well as a discoverable description. Those capabilities do not establish that an agent will choose the tool or use it correctly.
A fictional quote where two decimal places would lose information
Consider a fictional supplier preparing a read-only quote tool. Its catalogue can contain unit prices with up to six decimal places, but each quote has one currency. For this example, the supplier supports USD, JPY and KWD. This is a fictional application allowlist, not the complete ISO 4217 currency list or a payment provider’s supported-currency list. EUR is a real currency that this particular tool does not support.
The decision-changing input is a USD unit price of “1.005” with quantity 2. If the tool first rounds the unit price to “1.00” under round-half-even, it returns “2.00”. If it multiplies the exact price before rounding the quote total, it returns “2.01”. The supplier’s chosen rule for this fictional case is total-level rounding. Storing the input as whole cents would discard information that rule requires.
A local reference implementation, fictional-quote-money/1.0.0, was built and exercised on 17 October 2026 to test that contract. The intervention was to replace an ambiguous amount field with a required currency, a decimal-string amount, explicit quantity bounds and a single rounding rule. This is a synthetic calculation exercise, not an observed customer deployment, native WebMCP session or payment transaction.
The amount field must state its unit, grammar and scale
The input object contains exactly currency and lines. currency is a case-sensitive uppercase code from the three-code allowlist. lines contains one to five objects, each with exactly amount and quantity. For example: {“currency”:”USD”,”lines”:[{“amount”:”1.005″,”quantity”:2}]}. amount is a JSON string in major currency units. It is not an integer count of cents, a display label or a JSON floating-point number.
The accepted amount grammar is ^(0|[1-9][0-9]{0,6})(.[0-9]{1,6})?$, applied to the complete string. Amounts run from zero through 1000000 inclusive. A decimal point must have one to six following digits. Signs, whitespace, grouping commas, exponents, currency symbols and leading zeros such as “01.00” are rejected. Numeric 1.005, true and null are rejected rather than coerced into amounts. These are application rules, not restrictions imposed on every monetary API.
quantity is a JSON number with an integral value from 1 through 1000. The reference accepts 1.0 as the integer value 1, but rejects true, “1” and 1.5. Checking only whether a value looks truthy or can be converted to an integer would admit inputs outside this contract. An amount of “0” remains valid; it must not be mistaken for a missing value.
Input precision and output scale are different choices. This contract permits six fractional input digits for all three currencies, while its returned money uses scale 2 for USD, 0 for JPY and 3 for KWD. Scale 3 means a step of 0.001 major units, not a three-digit limit on the whole amount. The selected scales match the corresponding minor-unit entries in SIX’s current ISO 4217 list, inspected on 17 October 2026. They do not establish a universal rounding policy. Not every currency uses two decimal places.
A JSON Schema can express the required keys, string pattern, allowlist and array bounds. Application code must also check the numeric value of the amount string, the aggregate limit and the rounding sequence. The demonstration used explicit application validation; it did not exercise a separate JSON Schema validator. A schema declaration and a passing arithmetic test answer different questions.
Round once, at the boundary the quote promises
The implementation parses the amount string directly into Python Decimal, multiplies by the integer quantity and sums all lines before rounding. It sets a 40-digit arithmetic context, sufficient for the stated input and quantity bounds. It rejects an unrounded quote total above 1000000 major units, then quantizes the accepted total to the currency’s output scale. No input or individual line is rounded first. The returned amount is always a fixed-scale string, including trailing zeros.
Round-half-even chooses the nearest representable amount. At an exact halfway point, it chooses the result whose last retained digit is even. Under this contract, USD “1.005” becomes “1.00”, while “1.015” becomes “1.02”. Two USD lines of “1.005” each produce “2.01” after summation, not “2.00”. The rounding location changes the answer even when the rounding mode stays the same.
Python’s decimal documentation describes exact decimal representation, fixed-exponent quantization and selectable rounding modes. It also shows why constructing a Decimal from a binary float preserves the float’s approximation rather than recovering an intended decimal input. A string field helps only if the implementation keeps that distinction: converting the string to a float before constructing a Decimal would undermine this design. See the Python 3.12 decimal reference.
The output for the example is {“ok”:true,”money”:{“currency”:”USD”,”amount”:”2.01″},”rounding”:”HALF_EVEN”,”round_at”:”quote_total”}. For EUR, the result is {“ok”:false,”error”:{“code”:”UNSUPPORTED_CURRENCY”,”path”:”currency”}}. A boolean amount returns AMOUNT_TYPE at lines[0].amount. Errors return no partial total. The caller can distinguish an unsupported business currency from an incorrectly typed field without guessing from a human-readable sentence.

What the bounded replay established
Before implementation, 42 complete inputs and literal expected success or error objects were fixed. The fixture covered rounding ties, multiplication and summation order, zero values, unsupported and malformed currencies, amount types and grammar, quantities, object shape, line counts and upper bounds. Two fresh command-line processes then replayed the same fixtures under CPython 3.12.14 using only the standard library. Both matched all 42 expected objects, including output types, and produced identical output bytes.
- USD “19.99” × 3 returned “59.97”. The total-before-rounding example returned “2.01”.
- JPY “100.5” returned “100”; “101.5” returned “102”. KWD “1.2345” returned “1.234”; “1.2355” returned “1.236”.
- Zero returned “0.00” in USD, “0” in JPY and “0.000” in KWD. Five USD lines of “0.001” each returned “0.00” after total-level rounding.
- A unit amount of “1000000” with quantity 1 was accepted. “1000000.000001” failed AMOUNT_RANGE; “1000000” with quantity 2 failed TOTAL_RANGE.
A separate evaluator compared the outputs with a predeclared literal oracle. It also recomputed every successful fixture using rational arithmetic and integer quotient-and-remainder rounding, without importing the tool or using Decimal. Five deliberately incorrect submissions were rejected: half-up rounding, a fixed two-place scale, rejection of zero, acceptance of unsupported EUR and a numeric amount output in place of a string. These controls show that the evaluator could detect those particular defects. They are not independent human validation or proof against untested errors.
For the fictional supplier, the observable acceptance condition was exact agreement with every fixture and rejection of each incorrect submission. The local implementation met that condition. This supports choosing decimal-string inputs for this bounded quote task. It does not establish correct tax treatment, cash rounding, refund semantics, payment-provider compatibility or agent selection. Negative amounts, mixed currencies and totals above the bound remain outside the contract.
Change the representation when the task changes
Choose integer minor units instead when the upstream business contract already supplies amounts at final currency scale and no sub-minor-unit arithmetic is needed. The field must still carry its currency and documented exponent: 1234 at scale 3 means 1.234 major units, while at scale 2 it means 12.34. Define an integer range compatible with the chosen runtime and reject booleans. Integer storage removes one decimal parsing problem; it does not decide whether rounding belongs at unit, line or total level.
If the supplier later requires line-level rounding, the USD two-line fixture must change from “2.01” to “2.00” under half-even. If it adds another currency, its allowlist, output scale and boundary fixtures must change together. If it needs tax, discounts or signed adjustments, the current arithmetic sequence is no longer a complete contract. Those are reasons to revise and version the rules, not to let the agent infer them from a currency symbol.
Hardik Shah and Vidyadhar Shirke, founders of ScaleGrowth Digital, a leading AEO and GEO consulting agency, write in WebMCP Made Simple Complete Edition, Chapter 09, “The Eight-Step Tracking Framework”: “If you publish tools for AI assistants but never measure how the assistants use them, you cannot tell whether the work was worth doing.” For this quote tool, the practical consequence is to distinguish a tool invocation from a correct monetary result. The synthetic replay measured deterministic outputs. A later agent evaluation would also need to check whether the assistant selected the intended tool, supplied the intended currency and accurately reported the returned amount.
The WebMCP draft describes JavaScript tools with structured input schemas; the inspected 16 October 2026 report is not a W3C Standard. Chrome’s WebMCP debugging documentation distinguishes invocation inputs and outputs and permits manual testing that bypasses agent decision logic. Neither source turns a local Python replay into a native browser test. Registration, actual client behavior and application integration need their own versioned evidence.
ScaleGrowth’s WebMCP implementation service is relevant when the work includes defining these money semantics, building fixtures and carrying the contract into a scoped implementation. AgenticReadiness can help identify the task boundary; WebMCP consulting can address the tool contract. They should be scoped separately, not assumed to be automatically integrated. The useful handoff is a versioned currency policy, executable arithmetic and explicit failure outputs that the application team can reproduce before any agent-facing rollout.
References
Python 3.12 decimal documentation
https://docs.python.org/3.12/library/decimal.html
SIX ISO 4217 List One XML
https://www.six-group.com/dam/download/financial-information/data-center/iso-currrency/lists/list-one.xml
WebMCP draft
https://webmachinelearning.github.io/webmcp/
Chrome Debug WebMCP tools
https://developer.chrome.com/docs/devtools/application/webmcp
WebMCP Implementation, ScaleGrowth Digital
https://scalegrowth.digital/services/webmcp/