calculator
Evaluate mathematical and statistical expressions using Python syntax. Perform operations like arithmetic, list expressions, and use functions such as min, max, mean, and variance. Supports custom variables for advanced calculations in blockchain and crypto strategies.
Instructions
Safely evaluates a mathematical or statistical expression string using Python syntax.
Supports arithmetic operations (+, -, *, /, **, %, //), list expressions, and a range of math and statistics functions:
abs, round, min, max, len, sum, mean, median, stdev, variance, sin, cos, tan, sqrt, log, exp, floor, ceil, etc.
Custom variables can be passed via the 'variables' dict, including lists for time series data.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| expression | Yes | ||
| variables | Yes |
Implementation Reference
- armor_crypto_mcp/armor_mcp.py:100-111 (handler)The MCP tool handler for the 'calculator' tool. Decorated with @mcp.tool() for registration. Takes expression and variables, calls the calculate helper, and returns the result.@mcp.tool() async def calculator(expression:str, variables:dict[str, Any]): """ Safely evaluates a mathematical or statistical expression string using Python syntax. Supports arithmetic operations (+, -, *, /, **, %, //), list expressions, and a range of math and statistics functions: abs, round, min, max, len, sum, mean, median, stdev, variance, sin, cos, tan, sqrt, log, exp, floor, ceil, etc. Custom variables can be passed via the 'variables' dict, including lists for time series data. """ return {'result': calculate(expression, variables)}
- The core implementation of the calculator logic. A safe AST-based evaluator for mathematical expressions supporting operators, math/stats functions, variables, lists, and function calls.def calculate(expr: str, variables: dict = None) -> float: """ Evaluate a math/stat expression with support for variables and common functions. """ variables = variables or {} # Allowed names from math and statistics safe_names = { k: v for k, v in vars(math).items() if not k.startswith("__") } safe_names.update({ 'mean': statistics.mean, 'median': statistics.median, 'stdev': statistics.stdev, 'variance': statistics.variance, 'sum': sum, 'min': min, 'max': max, 'len': len, 'abs': abs, 'round': round }) # Safe operators ops = { ast.Add: operator.add, ast.Sub: operator.sub, ast.Mult: operator.mul, ast.Div: operator.truediv, ast.FloorDiv: operator.floordiv, ast.Mod: operator.mod, ast.Pow: operator.pow, ast.USub: operator.neg } def _eval(node): if isinstance(node, ast.Num): return node.n elif isinstance(node, ast.Constant): # Python 3.8+ return node.value elif isinstance(node, ast.BinOp): return ops[type(node.op)](_eval(node.left), _eval(node.right)) elif isinstance(node, ast.UnaryOp): return ops[type(node.op)](_eval(node.operand)) elif isinstance(node, ast.Name): if node.id in variables: return variables[node.id] elif node.id in safe_names: return safe_names[node.id] else: raise NameError(f"Unknown variable or function: {node.id}") elif isinstance(node, ast.Call): func = _eval(node.func) args = [_eval(arg) for arg in node.args] return func(*args) elif isinstance(node, ast.List): return [_eval(elt) for elt in node.elts] else: raise TypeError(f"Unsupported expression type: {type(node)}") parsed = ast.parse(expr, mode="eval") return _eval(parsed.body)