calculator
Evaluate mathematical expressions and perform statistical calculations using Python syntax. Supports arithmetic operations, math functions, and custom variables for cryptocurrency data analysis.
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-110 (handler)MCP tool handler for 'calculator': decorated with @mcp.tool() for registration and executes by calling the calculate helper function.@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)}
- Core helper function that implements safe evaluation of mathematical expressions using AST parsing, supporting variables, operators, math/stats functions.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)