Skip to main content
Glama
laszlopere

mcp-abacus

calculate

Evaluate arithmetic expressions or multi-line programs in fixed-point, floating-point, or rational modes. Each result includes exactness and precision labels.

Instructions

Evaluate an expression (or short program) in one numeric type; return value + precision.

Use `calculate` when you want the VALUE of an expression. To instead see WHERE a
surprising answer rounded or overflowed — the per-node parse tree with each
sub-result — use `analyze`; to find the variable value(s) that drive an
expression to a root or extremum, use `solver`. All three share this expression
language and `mode`/`min_fixed_point_precision` arguments.

`mode` is the numeric type the WHOLE calculation runs in — every intermediate
result behaves exactly as that type would, so float rounding, fixed-point
scale, and rational exactness each show through. Modes:
  fixed-point   (default) exact scaled integer; money / ERC-20-safe; alias decimal
  floating-point  IEEE-754 double; ~15-17 sig. digits; aliases float64, double, float, ieee754
  rational        exact numerator/denominator; no irrationals; aliases fraction, frac

Grammar. Binary `+ - * / // %`; unary prefix `+ - ~`; `**` is POWER,
right-assoc, binds tighter than unary minus: -2**2 == -(2**2). Bitwise
`& | ^` (^ is XOR, NOT power) and `~` (NOT) work in EVERY type, on its own
stored bits (float's 64-bit IEEE pattern, fixed-point's mantissa, rational's
numerator/denominator). Both operands
of a binary op must share ONE type — there is no implicit promotion. Group
with `( )`. Functions: call as `name(arg, ...)` — e.g. `sqrt`, `sin`, `sum`;
each argument evaluates in the active type. For the full set and their
argument counts call `help('functions')`. Constants: `pi` and `e` are usable
bare (no parentheses), e.g. `2*pi`; assigning to them is an error. Literals: decimals
`12 3.14 .5 1e3 2.5e-4`; base integers
`0x1F 0b1010 0o17`; fixed-point `M@D == M x 10^-D`, where M MUST be
base-prefixed (0x/0o/0b) — a DECIMAL mantissa is INVALID: both `123@2` and
`123.45@2` error; write a decimal value as its digits (e.g. 123.45), never
with `@`. (`0x59682F00@9` = 1.5, `0xDE0B6B3A7640000@18` = 1 ETH.)

Variables & multi-line programs. Assign with `name = expr` (name is an
identifier `[A-Za-z_][A-Za-z0-9_]*`); a bare `name` reads it back, and reading
a name that was never assigned is an error. An assignment is itself an
expression — its value is the right-hand side — so `x = 2 + 3` returns 5 and
also binds `x`. Pass SEVERAL statements as one `expression` by separating them
with NEWLINES (`

): they run top to bottom sharing one variable scope, so a later line sees earlier bindings. EVERY bare-expression line is answered, in source order, in the valuesarray (below); assignment lines run silently for their bindings and are NOT echoed — except the final line, which is always the program's result and so is always echoed. When more than one line is answered, the top-level valueis a multi-line transcript, one = per answered line; a single answered line keepsvalueas just that result. E.g. "x = 10 y = x * 2 y + 1"returns 21 (onlyy + 1is a bare line), while "x = 10 (x - 1) / (x + 1) (x + 1) / 100.0"answers both divisions. Scope lasts for the one call only — bindings do not carry over to the nextcalculate`.

Returns a dict: `value` is the result rendered as a string and ANNOTATED with
its precision verdict — "(exact)" when the result is the true value, else
"(inexact, rounded to N decimals)" — so e.g. `/` cannot silently mislead by
looking exact when it rounded. `value_hex_dump` is that same value in hex (the
bit-backed representation): fixed-point as M@D (mantissa in whole-byte hex,
`@scale` dropped at scale 0), floating-point as the raw 64-bit IEEE-754
pattern, and NULL in rational mode (a numerator/denominator pair has no single
integer to dump). `mode` is the RESOLVED numeric type the call ran in — always
the canonical name even when you passed an alias (e.g. "double" reads back as
"floating-point"), so the reply stands on its own. The exactness/scale facts
are also returned as separate fields: `exact` (bool — did the mode hold the
true value) and `precision` (the fixed-point decimal scale, or null when the
mode has none). NOTE: floating-point conservatively reports `exact: false` for
every result today, including ones a double holds exactly. `values` is the per-line
breakdown: an array with one object per answered line, in source order, each
`{source, value, value_hex_dump, exact, precision, offered_precision}` — `source` is
the re-rendered expression and the other fields mirror the top-level ones for that one
line. The LAST entry is the program's result, so its fields equal the top-level
`value_hex_dump`/`exact`/`precision`/`offered_precision` (and, for a single answered
line, the top-level `value`). On failure `value`/`value_hex_dump`/`mode`/`exact`/
`precision`/`offered_precision`/`values` are null and `error` carries a plain,
self-contained message — what went wrong (a malformed expression, a domain error,
or an unknown mode with the valid list). It reads as prose, not a log line; only
the inexact-abort diagnostic names its source line, and in prose. On success
`error` is null. For the full reference call `help`.

`min_fixed_point_precision` floors the fixed-point result at that many decimal
places: every operand is held at no fewer than that many fractional digits, so
a `/` that would otherwise round at scale 0 keeps more decimals. It is valid
ONLY in fixed-point mode (the other modes have no decimal scale) and must be a
non-negative integer; either violation is an `error`. Omit it (null) for no
floor.

`inexact_handling` chooses what happens when a result is INEXACT:
  continue-and-report  (default) evaluate normally and let the verdict surface
                       in `value`/`exact`; never reject. Aliases: continue, report.
  abort-on-inexact     stop and FAIL the moment any sub-result is inexact. The
                       call returns no value — `error` instead carries a
                       diagnostic naming the source line and laying out the
                       operation that went inexact in computed VALUES (e.g.
                       `1.00 / 3.00 = 0.33`), then how to enable inexact
                       calculations if you do want the rounded answer. Use it
                       when an approximate answer is unacceptable and you want to
                       be told precisely what and where, rather than silently
                       trusting a rounded figure. Aliases: abort, strict, exact-only.
An unknown value is an `error` listing the valid choices. Note floating-point
reports every result inexact, so abort-on-inexact there fails on the first value.

`offered_precision` is a what-if nudge, present (non-null) ONLY on an inexact
fixed-point result when you did NOT pass min_fixed_point_precision: it shows the
SAME expression at a few more decimals so you see the digits the rounding hid.
It is a nested object `{mode, min_fixed_point_precision, value, value_hex_dump,
exact}` mirroring the top-level reply — its `mode` is always "fixed-point", its
min_fixed_point_precision is the argument to pass to GET that fuller value, its
`value` is what you'd get back (annotated with its OWN precision verdict, since
the offered value may itself still be inexact — e.g. 10/3 never terminates),
and `value_hex_dump` is that offered value in hex. It is NOT the answer to the
call you made (that stays in the top-level `value`); it is null whenever there
is nothing to offer. Each `values` entry carries its OWN `offered_precision` under
the same gate, so every answered line steers independently.

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
modeNoNumeric type the WHOLE calculation runs in: 'fixed-point' (default; exact scaled integer, money/ERC-20-safe; alias 'decimal'), 'floating-point' (IEEE-754 double; aliases 'float64', 'double', 'float', 'ieee754'), or 'rational' (exact numerator/denominator; aliases 'fraction', 'frac'). Note 'decimal' resolves to fixed-point, NOT a decimal float. `help('types')` lists the full set.fixed-point
expressionYesThe expression, or a newline-separated multi-line program (`name = expr` assignments sharing one scope), to evaluate.
inexact_handlingNoWhat to do when a result is inexact: 'continue-and-report' (default; evaluate and let the precision verdict surface) or 'abort-on-inexact' (fail on the first inexact sub-result).continue-and-report
min_fixed_point_precisionNoFloor fixed-point results at this many decimal places (non-negative integer). Valid ONLY in fixed-point mode; null for no floor.
Behavior5/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It extensively discloses behaviors: no implicit type promotion, bitwise operations on all types, variable scoping per call, floating-point always reports exact=false, error messages are prose, offered_precision nudge, etc. No contradictions.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is long but well-organized with sections (grammar, variables, return value, etc.) and front-loaded with purpose and sibling differentiation. Some details could be referenced to `help`, but for a complex tool the length is justified. Efficient use of sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness5/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a tool with 4 parameters, no output schema, and complex behavior (multi-line programs, nested return values, error handling, offered_precision), the description covers all necessary aspects: input format, output structure, error messages, mode constraints, inexact handling, and even edge cases (e.g., fixed-point literal rules). Very complete.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters5/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so baseline is 3. Description adds substantial value beyond schema: explains mode aliases (e.g., 'decimal' resolves to fixed-point), min_fixed_point_precision floor behavior and validity constraints, inexact_handling options with aliases and examples, and expression grammar with constants, literals, and variable assignments.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool evaluates an expression and returns value and precision. It explicitly distinguishes from siblings (analyze, solver, help) by naming them and explaining their different purposes. The verb 'calculate' and resource 'expression' are specific.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Provides explicit guidance on when to use calculate vs analyze (to see per-node rounding) vs solver (to find variable values driving to root/extremum). Also explains when to use each mode (fixed-point, floating-point, rational) and the inexact_handling options. No ambiguity.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

Install Server

Other Tools

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/laszlopere/mcp-abacus'

If you have feedback or need assistance with the MCP directory API, please join our Discord server