mcp-abacus
mcp-abacus is a type-faithful calculator MCP server for AI models that evaluates mathematical expressions with precision annotations — every result is labelled with how accurate it is.
calculate— Evaluate expressions or multi-line programs in a chosen numeric type:Fixed-point (default): exact scaled integers, safe for financial calculations
Floating-point: IEEE-754 double precision
Rational: exact numerator/denominator arithmetic with no rounding
Complex:
a + b*iarithmetic over fixed-point partsReturns results annotated with precision verdicts (
exactvsinexact, rounded to N decimals)Supports
abort-on-inexactmode and vector literals for statistical operations (min, max, avg, median, variance, stddev, etc.)
analyze— Evaluate an expression and return its full parse tree, with every sub-expression annotated with its computed value and precision, so you can pinpoint exactly where rounding or overflow occurred.solver— Find variable values that drive an expression to a root or extremum:Modes:
find-root,find-minimum,find-maximumSingle- or multi-variable search with bracketed ranges
Algorithms include golden-section, Brent parabolic, bisection, Newton-Raphson, Halley, Nelder-Mead simplex, BFGS, and more
curve_fit— Fit known curve forms (linear, polynomial, power law, exponential, Gaussian, logistic, sinusoidal, Weibull, etc.) to(x, y)data points, returning the best fits ranked by residual error with parameters in the chosen numeric type.help— Returns reference documentation for the expression grammar, numeric types, available functions, and the solver tool.info— Reports server version, availability, and environment information.
mcp-abacus
A calculator for the artificial minds — because we know their needs are different.
People reach for a calculator to get a number. A language model reaches for one to get a number it can trust and reason about: Was this exact, or rounded? At what scale? Would a wider type have held more digits? Does this overflow the way the production code will? A floating-point answer that merely looks precise is worse than no answer — it launders a rounding error into a confident claim.
mcp-abacus is built for that caller. It does type-faithful calculation: you
pick a numeric type/mode (fixed-point, IEEE-754 double, exact rational, complex) and the
whole expression behaves exactly as that type would in real code — it rounds
where the type rounds, stays exact where the type is exact, and carries the
result onward bit-for-bit. Every answer comes back labelled with its own
precision verdict (exact vs inexact, rounded to N decimals), so the model
never has to guess whether a result is the true value. It does not approximate a
type; it calculates using that type.
What it gives you
calculate— evaluate one expression in one numeric type. Modes:fixed-point(default) — exact scaled integer; money / ERC-20-safefloating-point— IEEE-754 double (aliasesfloat64,double)rational— exact numerator/denominator; no silent roundingcomplex—a + b*iover two fixed-point parts; write the imaginary unit as1i(e.g.3+4i,2.5i). Exact+ - *((3+4i)*(1+2i)→-5+10i,sqrt(-1)→1i), rounds/and the transcendentals onto the grid; no ordering, bitwise, integer (gcd/factorial), or solver support
A vector literal
[a, b, …]builds a one-dimensional list of values in the chosen mode (e.g.[1, 2, 3], the empty[], or[1+1, 2*3]→[2, 6]); it is an internal container, not a selectable mode. The whole stats family reduces over a single vector's elements —min/max/avg/median/variance/stddev/sumsq/geomean/harmean(avg([1, 2, 3])→2,sumsq([1, 2, 3])→14,geomean([4, 9])→6), as do the integer reducersgcd/lcm(gcd([54, 24, 6])→6). The order statistics take a leading point then the data (a run or one vector):quantile(q, …)forqin[0, 1]andpercentile(p, …)forpin[0, 100]read the value at that rank (type-7 linear interpolation), generalisingmedian—percentile(50, [1, 2, 3, 4])is the median. Andcovariance(x, y)/correlation(x, y)take two equal-length vectors (covariance([1, 2, 3], [4, 5, 6]), Pearsoncorrelation(...)in[-1, 1]). Going the other way,factor(n)PRODUCES a vector — the prime factors of a positive integer, ascending with multiplicity (factor(12)→[2, 2, 3],factor(1)→[]). Otherwise vectors only construct and render — other operators and functions refuse one, there is no indexing (b[i]), and nesting ([[1,2],[3,4]]) is rejected.analyze— evaluate an expression and return its whole parse tree, each node annotated with the value it computed, so you can see where a surprising answer rounded or overflowed (e.g.(1 + 1/2) * 3is3in fixed-point — the tree shows the1/2 = 0leaf that explains it)solver— find the value(s) of one or more variables that drive an expression to a target over a bracket: find-root (x**2 - 2over[0, 2]→ √2) or find-minimum / find-maximum, in the same numeric type and expression language (constants come fromname = exprassignment lines). One unknown uses golden-section search (or Brent parabolic viaalgorithm="brent-parabolic", usually faster on smooth extrema, or plain ternary search viaalgorithm="ternary-search", or — for an extremum only — Newton viaalgorithm="newton-optimise", which steps to the zero of the objective's own slope and lands a quadratic in one step; or, for a root, the sign-change bracketersalgorithm="bisection","ridders","brent-dekker","chandrupatla"and"secant", or the bracket-freealgorithm="newton-raphson"/"halley", which follow the expression's own derivatives and so also reach a root that only touches zero); passvariables(a name →[lower, upper]map) with a multivariate engine to solve several jointly —algorithm="nelder-mead"for the derivative-free Nelder-Mead simplex (any objective),algorithm="powell"for Powell's direction set, derivative-free too and usually the cheapest of the three on a smooth objective, oralgorithm="bfgs"for quasi-Newton gradient descent (extrema only, far fewer iterations on a smooth bowl)curve_fit— fit known curve forms to paired(x, y)observations and report each fitted equation with its error. Hand over the data and it estimates, for the straight line, quadratic, cubic, power lawa*x**b, exponentiala*exp(b*x), exp-reciprocal (Arrhenius)a*exp(b/x), logarithma + b*ln(x), square roota*sqrt(x) + b, reciprocala/x + b, sinusoida*sin(b*x + c) + d, gaussiana*exp(-(x-b)**2/(2*c**2)), saturationx/(a*x + b)(Michaelis-Menten), hyperbolic1/(a*x + b), Laurenta + b*x + c/x, Hoerla*b**x*x**c, Weibull CDF1 - exp(-(x/a)**b), logistica/(1 + exp(-(b*x + c)))(with a data-fixed ceilinga), generalized hyperbolic1/(a*x**2 + b*x + c)and Lorentzian peaka/(1 + ((x-b)/c)**2), the parameters that best match in the least-squares sense — polynomials and the affine forms in closed form via the normal equations, the power, exponential and exp-reciprocal laws by a log-linearisation, the gaussian and Hoerl by fitting a log-space basis (Caruana's method for the gaussian), the Weibull by the double-log Weibull plot, the logistic by the logit once its ceiling is fixed, the saturation and hyperbolic by a reciprocal-line transform (the generalized hyperbolic and Lorentzian by a reciprocal-quadratic), and the sinusoid (the lone form with no closed form) by an iterative frequency search — then ranks them by residual error and returns the best three (e.g.x=[1,1.5,2], y=[2,5.8,8.9]→6.9*x - 4.78…). The whole fit runs in the chosen numeric type, so the parameters and error carry the usual precision verdicthelp— the grammar and type reference, on tap for the modelinfo— server version and environment
Each calculate result is self-describing: a rendered value string with its
precision verdict baked in, plus structured exact / precision fields. An
inexact fixed-point result even previews what a few more decimals would reveal,
so the caller is steered toward more precision rather than toward a misleading
float.
Related MCP server: symath
Install and register for Claude Code
Install the server as a uv tool from this checkout:
uv tool install .This puts an mcp-abacus executable on your PATH. Register it with Claude Code
(user scope, so it's available in every project):
claude mcp add abacus -- mcp-abacusThen start (or /mcp reconnect) a Claude Code session — the abacus tools will
be available. Verify the server is up with:
claude mcp listUpgrading from source: the version is pinned, so a plain reinstall can reuse a cached wheel and silently install stale code. Force a clean rebuild:
uv cache clean mcp-abacus uv tool install --force --no-cache .A long-lived Claude session keeps the old server subprocess until you
/mcpreconnect or start a fresh session.
Development
uv sync
uv run pytestSponsoring
mcp-abacus is free, open-source software developed in my spare time. Sponsorships are what keep the project alive and actively maintained — they fund new numeric modes, bug fixes, and ongoing support, and they're a direct signal that the work is worth continuing.
If the project is useful to you, please consider sponsoring it through GitHub Sponsors. Click the Sponsor button at the top of the repository, or visit the link directly, and pick a one-time or recurring tier. Every contribution, large or small, is hugely appreciated and goes straight back into keeping mcp-abacus healthy.
License
GNU General Public License v3.0 or later (GPL-3.0-or-later). See LICENSE.
Available Tools
5 toolsanalyzeA
Evaluate an expression and return its AST as an indented tree of sub-results.
Same arguments and evaluation as calculate — mode (fixed-point default,
floating-point, rational) and min_fixed_point_precision behave identically —
but instead of one final value this returns the WHOLE parse tree, each node
annotated with the Value it computed in that mode. Reach for it to see WHERE a
surprising answer comes from: which sub-expression rounded, overflowed, or lost
precision, rather than only the rounded result. For just the final value use
calculate; to find the variable value(s) that drive an expression to a root or
extremum, use solver.
tree is a multi-line string, one node per line, indented by depth (root last-
applied operator at the top, literals at the leaves). Each line is
<OPCODE/LITERAL "lexeme"> Value = <value> (<type>[<scale>], <exact|inexact>)
followed by ·-separated per-mode details: the value in hex (fixed-point as
M@D with whole-byte digits, @<scale> dropped at scale 0; float as raw IEEE-754
bits), or a rational's decimal approximation. The <scale> is the fixed-point
decimal scale (omitted for modes without one). A fixed-point node that ROUNDED
its result also carries a final · rounding <residual> ≈ <approx> fragment: the
exact signed residual stored − true (a fraction, bounded by half a unit in the
last place) and its decimal approximation. It is named rounding, NOT error,
on purpose — the reply's top-level error field is the failure channel, so a
rounding label keeps "this node rounded" from being misread as "this node
failed". For example (1 + 1/2) * 3 in fixed-point:
BINARY_MUL Value = 3 (fixed-point[0], inexact) · hex 0x03
BINARY_ADD Value = 1 (fixed-point[0], inexact) · hex 0x01
LITERAL "1" Value = 1 (fixed-point[0], exact) · hex 0x01
BINARY_DIV Value = 0 (fixed-point[0], inexact) · hex 0x00 · rounding -1/2 ≈ -0.5
LITERAL "1" Value = 1 (fixed-point[0], exact) · hex 0x01
LITERAL "2" Value = 2 (fixed-point[0], exact) · hex 0x02
LITERAL "3" Value = 3 (fixed-point[0], exact) · hex 0x03— the 1/2 = 0 leaf (inexact, scale 0) makes plain that fixed-point rounded the
half away (its rounding -1/2 is the exact half discarded), so the product is 3,
not 4.5, and every node above it inherits the inexactness. Those ancestors show no
rounding fragment: they introduced no rounding of their own, only carried the
leaf's. (Raise min_fixed_point_precision, or use a different mode, to keep those
digits.)
On success tree is the rendering and error is null; on a bad mode, an invalid
min_fixed_point_precision, or a malformed/erroring expression, tree is null and
error carries the message (the same messages calculate returns).
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Numeric type to evaluate in: 'fixed-point' (default), 'floating-point', or 'rational' — as in `calculate`. | fixed-point |
| expression | Yes | The expression or newline-separated program to parse and evaluate; same grammar as `calculate`. | |
| min_fixed_point_precision | No | Floor on fixed-point fractional digits (non-negative integer); fixed-point mode only, null for no floor — as in `calculate`. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description bears full burden. It thoroughly describes the output format (tree, each node with opcode, value, type, exactness, rounding details), error handling (null tree with error message on failure), and the naming choice 'rounding' to avoid confusion with the error field. This is highly transparent.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is long but well-structured: it starts with a clear purpose, then explains output format with an example, and ends with error handling. Every sentence adds necessary information for a complex tool, with no redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the high complexity (AST output, multiple modes, rounding details) and absence of output schema or annotations, the description is remarkably complete. It covers output format, error cases, example, and ties to sibling tools, leaving no significant gaps.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, so baseline is 3. The description adds value by explaining that 'mode' and 'min_fixed_point_precision' behave identically to 'calculate', providing context beyond the schema's parameter descriptions.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
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 its AST as an indented tree of sub-results. It distinguishes from siblings 'calculate' and 'solver' by specifying that this tool is for understanding where surprising answers come from, not just final values.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Explicitly contrasts with 'calculate' (for final value) and 'solver' (for variable values driving to root/extremum). Also notes same arguments and evaluation as 'calculate', providing clear guidance on when to use this tool versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
calculateA
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.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Numeric 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 |
| expression | Yes | The expression, or a newline-separated multi-line program (`name = expr` assignments sharing one scope), to evaluate. | |
| inexact_handling | No | What 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_precision | No | Floor fixed-point results at this many decimal places (non-negative integer). Valid ONLY in fixed-point mode; null for no floor. |
TDQS
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.
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.
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.
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.
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.
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.
helpA
Return mcp-abacus reference text for one section, to drive the evaluator.
Sections: 'types' (the numeric types this build supports), 'language' (the
expression grammar — operators, precedence, literal forms), 'functions' (the
callable functions and their argument counts), and 'solver' (the solver tool —
solving / optimising one variable over a bracket). section is restricted to
these four names — advertised as a schema enum — so any other value is rejected
with the valid list.
| Name | Required | Description | Default |
|---|---|---|---|
| section | Yes | Which reference section to return: 'types', 'language', 'functions', or 'solver'. |
Output Schema
| Name | Required | Description |
|---|---|---|
| result | Yes |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations provided, so the description carries the burden. It discloses the validation behavior (section restricted to four values). However, it does not describe return format, size, or other traits. Adequate for a simple tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Two efficient sentences front-load the core purpose and then detail sections. No wasted words; every sentence earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given the tool's simplicity and presence of an output schema, the description covers key aspects: section definitions and validation. Slightly lacking on return type details, but output schema likely compensates.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, baseline is 3. The description adds value by elaborating what each section contains (e.g., 'numeric types', 'expression grammar'), providing context beyond the enum values.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states the tool returns reference text for one section, specifying the verb ('Return'), resource ('mcp-abacus reference text'), and scope ('for one section'). It distinguishes from sibling tools by focusing on documentation retrieval.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description implies usage for obtaining reference text but does not explicitly contrast with sibling tools or provide when-to-use/when-not-to-use guidance. Context is clear but lacks explicit exclusions.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
infoA
Report mcp-abacus server availability, version, and environment information.
toolsets lists the opt-in tool groups active in this build. It is EMPTY today —
every tool registers unconditionally — and is reserved for the future toolset
gating (SA.1); it is reported now so a client can read the active set once that
lands.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
No annotations are provided, so the description carries the full burden. It discloses that the tool reports availability, version, and environment info, and explains the toolsets field's current and future meaning. This is sufficient for a read-only info tool.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is two sentences plus one explanatory paragraph. The main purpose is front-loaded, and each sentence adds value without redundancy.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no parameters, no annotations, and no output schema, the description provides enough context about the tool's output (availability, version, environment info) and explains the toolsets field. It is complete for the tool's simplicity.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema is empty (0 parameters), so the description does not need to add parameter meaning. Per guidelines, 0 parameters yield a baseline score of 4.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description uses a specific verb 'Report' and clearly identifies the resource: 'mcp-abacus server availability, version, and environment information.' This distinguishes the tool from siblings like analyze, calculate, help, and solver.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description clearly states the tool's function, implying when to use it (to get server info), but does not explicitly mention when not to use it or suggest alternatives. The sibling names provide indirect differentiation.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
solverA
Find the value(s) of one or more variables that drive an expression to a root or extremum.
solver takes the SAME expression language as calculate — every operator,
function, literal form, and (crucially) multi-line programs with name = expr
assignments — but instead of evaluating the expression it SEARCHES for the value
of the unknown(s) that drive the expression to the chosen objective:
"find-root" (default): find where the expression equals zero. Write an equation
f = gas the expressionf - gand find its root."find-minimum" / "find-maximum": find where the expression reaches its smallest / largest value within the bracket(s).
There are two input forms for the unknowns:
SINGLE:
variable+lower+upper— one unknown searched over the bracket[lower, upper](lowermust be belowupper). This is the default golden-section engine.MULTIPLE:
variables— a dict mapping each unknown name to its[lower, upper]bracket, e.g.{"x": [0, 5], "y": [-4, 2]}. This needs the Nelder-Mead engine (algorithm="nelder-mead"), which searches all the unknowns jointly. Give exactly one of the two forms. Each unknown must OCCUR in the expression and must NOT be assigned by it; every OTHER name is a constant the program sets via an assignment line (e.g."r = 0.05\np = 1000\np * (1 + r)**n - 2000"solving fornwithr,pfixed). A name that is neither an unknown nor assigned is an error.
objective (optional) names what to search for — "find-root", "find-minimum", or
"find-maximum"; omitted, it defaults to "find-root". (The older spellings solve,
minimise/maximise and their min/max and American forms are accepted too.)
algorithm (optional) names the search engine — "golden-section-search" (the
default, single-variable), "brent-parabolic" (single-variable too, parabolic
interpolation with a golden-section fallback — usually faster on smooth extrema),
or "nelder-mead" (multivariate, a bounds-clamped downhill simplex). The two
single-variable engines solve only the SINGLE form; the variables form requires
"nelder-mead". (golden, brent, simplex and a few other spellings are accepted
too.)
mode and min_fixed_point_precision behave as in calculate — the search runs
in that numeric type and the found value is reported in it — with ONE solver-only
rule: in fixed-point mode (the default) min_fixed_point_precision is REQUIRED.
Without it the search would run at scale 0, flooring the variable to whole numbers
and missing any non-integer solution, so the call is refused; pass it (e.g. 9), or
switch to floating-point / rational, which resolve sub-unit values natively and
need no floor. See calculate and help for the shared grammar and modes; if a
found value or objective looks off, analyze shows the per-node parse tree of the
expression (with the unknowns substituted) to reveal where it rounded or overflowed.
The search is bounded by a hard 2-second time limit. If it has not converged by then it stops and reports the best value reached so far (a find-root that has not got close enough to zero in that time is reported as no-solution, naming the limit).
Returns a dict: solutions is a list of {variable, solution, solution_hex_dump},
one per unknown in input order — each solution rendered and marked "(approximate)"
(the search locates it to a tolerance, never exactly), with its bit-backed hex. For
the SINGLE form the scalar variable / solution / solution_hex_dump are also
set (the one unknown); for the MULTIPLE form those scalars are null and solutions
carries every value. value is the EXPRESSION evaluated at that solution, annotated
with its own precision verdict (near zero for find-root, the extremum otherwise),
and value_hex_dump its hex. mode is the resolved numeric type; exact and
precision describe value exactly as in calculate. objective echoes the
resolved objective, algorithm names the engine used, and iterations is how many
search steps it took. On any failure — a bad mode/precision, a malformed expression,
an invalid request (no/both input forms, empty bracket, unknown not in the
expression, golden-section asked for multiple unknowns, unknown objective or
algorithm), or no solution in the bracket — every data field is null and error
carries the message (a no-solution error reports the closest |expr| it reached); on
success error is null.
| Name | Required | Description | Default |
|---|---|---|---|
| mode | No | Numeric type the search runs in: 'fixed-point' (default), 'floating-point', or 'rational' — as in `calculate`. | fixed-point |
| lower | No | SINGLE form: lower bound of the search bracket for `variable` (must be below `upper`). Part of the variable+lower+upper trio; leave unset when using the `variables` form. | |
| upper | No | SINGLE form: upper bound of the search bracket for `variable` (must be above `lower`). Part of the variable+lower+upper trio; leave unset when using the `variables` form. | |
| variable | No | SINGLE-unknown form: name of the one variable to search for, used together with `lower`+`upper`. Give EXACTLY ONE input form: this trio, OR `variables` (never both, never neither). | |
| algorithm | No | Search engine: 'golden-section-search' (default, single-variable), 'brent-parabolic' (single-variable), or 'nelder-mead' (required for the `variables` form). | |
| objective | No | What to search for: 'find-root' (default), 'find-minimum', or 'find-maximum'. | |
| variables | No | MULTIPLE-unknown form: dict mapping each unknown name to its [lower, upper] bracket, e.g. {"x": [0, 5], "y": [-4, 2]}; requires algorithm='nelder-mead'. Give EXACTLY ONE input form: this, OR `variable`+`lower`+`upper` (never both, never neither). | |
| expression | Yes | The expression (or newline-separated program whose `name = expr` lines set constants) to drive to a root or extremum; same grammar as `calculate`. | |
| min_fixed_point_precision | No | Floor on fixed-point fractional digits (non-negative integer). REQUIRED in fixed-point mode (else the search floors to integers); null/omit in the other modes. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Despite no annotations, the description fully discloses behavioral traits: 2-second time limit, convergence behavior, error handling, fixed-point precision requirement, and input constraints. 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.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is well-structured with clear sections and bullet points, and is front-loaded with the main purpose. However, it is quite long; some details could be condensed without losing clarity.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
Given no output schema, the description explains the return format in full detail including all fields, edge cases, and error states. Covers input, behavior, and output comprehensively.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, but the description adds substantial meaning beyond parameter names: explains expression language, single vs multiple forms, algorithm details, mode interplay, and precision requirements. Every parameter is contextualized.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description clearly states it finds variable values to drive an expression to a root or extremum, distinguishing from sibling tools like calculate (evaluate) and analyze (debug parse tree). The verb 'find' plus resource 'solver' is specific.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Extensive guidance on when to use single vs multiple variables, which algorithm to choose, and modes. Explicitly references calculate, analyze, and help for alternative contexts. Provides explicit 'when-not' and alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
TDQS
Each tool has a distinct purpose: calculate returns values, analyze shows parse tree, help provides reference, info reports server status, solver finds variable values. No overlap in functionality.
All tool names are single verbs or nouns in lowercase (analyze, calculate, help, info, solver), following a consistent and predictable pattern.
With 5 tools, the server is well-scoped for a calculator/solver domain. Each tool serves a clear role without being too few or too many.
The set covers evaluation, deep analysis, help documentation, server info, and solving. No obvious gaps for the stated purpose.
Maintenance
Resources
Unclaimed servers have limited discoverability.
Looking for Admin?
If you are the server author, to access and configure the admin panel.
Related MCP Connectors
Educational MCP server with 17 math/stats tools, visualizations, and persistent workspace
QuLab MCP remote server (Streamable HTTP) for computational science and lab tools.
This MCP server enables users to perform scientific computations regarding linear algebra and vect…
MCP server for progressive tool usage at any scale (see https://klavis.ai)
Related MCP Servers
- FlicenseNot gradedqualityCmaintenanceA Python-based MCP server that provides mathematical tools like addition and random number generation, plus server metadata.
- AlicenseBqualityCmaintenanceHigh-precision mathematics server for MCP clients, providing exact integer arithmetic, symbolic derivatives, and numerical calculus via LaTeX-style input.6172MIT
- AlicenseAqualityAmaintenanceAn MCP server that performs exact arithmetic calculations, avoiding the pitfalls of float64 and unsafe eval, with resource limits for safe execution.1MIT
- AlicenseAqualityBmaintenanceMCP server for deterministic numeric verification and spreadsheet auditing. Enables AI agents to verify math/finance claims, audit rows, and evaluate covenant rules with signed, independently checkable receipts.4MIT
Latest Blog Posts
- Who's Calling? MCP Hosts Are an Identity Blind Spot (And the Spec Knows It)By Om-Shree-0709 on .mcpAgent IdentityOAuth 2.1
- Your AI Chatbot Just Exposed Your CEO's Salary to an InternBy Om-Shree-0709 on .Agent IdentityMCP SecurityOAuth Delegation
- Why MCP Servers Need Execution Sandboxing (And Why Your Current Stack Isn't Enough)By Om-Shree-0709 on .Agentic AiPrompt InjectionWebAssembly
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