Skip to main content
Glama
by apetta
basic.py7.74 kB
"""Basic mathematical calculation tools.""" import math from typing import Annotated, Dict, Literal, Union, List from pydantic import Field from sympy import sympify, simplify, N from mcp.types import ToolAnnotations import numpy as np from ..server import mcp from ..core import format_result @mcp.tool( name="calculate", description="""Evaluate mathematical expressions using SymPy. Supports: - Arithmetic: +, -, *, /, ^ - Trigonometry: sin, cos, tan, asin, acos, atan - Logarithms: log, ln, exp - Constants: pi, e - Functions: sqrt, abs Examples: SIMPLE ARITHMETIC: expression="2 + 2" Result: 4 TRIGONOMETRY: expression="sin(pi/2)" Result: 1.0 WITH VARIABLES: expression="x^2 + 2*x + 1", variables={"x": 3} Result: 16 MULTIPLE VARIABLES: expression="x^2 + y^2", variables={"x": 3, "y": 4} Result: 25""", annotations=ToolAnnotations( title="Expression Calculator", readOnlyHint=True, idempotentHint=True, ), ) async def calculate( expression: Annotated[ str, Field( description="Mathematical expression (e.g., '2+2', 'sin(pi/2)', 'x^2+1')", min_length=1 ), ], variables: Annotated[ Dict[str, float] | None, Field(description="Variable substitutions (e.g., {'x': 5, 'y': 10})"), ] = None, ) -> str: """Evaluate mathematical expressions.""" try: expr = sympify(expression) if variables: result = float(N(expr.subs(variables))) else: result = float(N(simplify(expr))) return format_result(result, {"expression": expression, "variables": variables}) except Exception as e: raise ValueError( f"Failed to evaluate expression '{expression}'. " f"Error: {str(e)}. " f"Example: '2*x + 3' with variables={{'x': 5}}" ) @mcp.tool( name="percentage", description="""Perform percentage calculations: of, increase, decrease, or change. Examples: PERCENTAGE OF: 15% of 200 operation="of", value=200, percentage=15 Result: 30 INCREASE: 100 increased by 20% operation="increase", value=100, percentage=20 Result: 120 DECREASE: 100 decreased by 20% operation="decrease", value=100, percentage=20 Result: 80 PERCENTAGE CHANGE: from 80 to 100 operation="change", value=80, percentage=100 Result: 25 (25% increase)""", annotations=ToolAnnotations( title="Percentage Calculator", readOnlyHint=True, idempotentHint=True, ), ) async def percentage( operation: Annotated[ Literal["of", "increase", "decrease", "change"], Field(description="Type of calculation") ], value: Annotated[float, Field(description="Base value")], percentage: Annotated[ float, Field(description="Percentage amount (or new value for 'change')") ], ) -> str: """Perform percentage calculations.""" try: if operation == "of": result = (percentage / 100) * value explanation = f"{percentage}% of {value}" elif operation == "increase": result = value * (1 + percentage / 100) explanation = f"{value} increased by {percentage}%" elif operation == "decrease": result = value * (1 - percentage / 100) explanation = f"{value} decreased by {percentage}%" elif operation == "change": # percentage is actually the new value in this case if value == 0: raise ValueError("Cannot calculate percentage change from zero") result = ((percentage - value) / value) * 100 explanation = f"Percentage change from {value} to {percentage}" else: raise ValueError(f"Unknown operation: {operation}") return format_result( result, { "operation": operation, "value": value, "percentage": percentage, "explanation": explanation, }, ) except Exception as e: raise ValueError(f"Percentage calculation failed: {str(e)}") @mcp.tool( name="round", description="""Advanced rounding operations with multiple methods. Methods: - round: Round to nearest (3.145 → 3.15 at 2dp) - floor: Always round down (3.149 → 3.14) - ceil: Always round up (3.141 → 3.15) - trunc: Truncate towards zero (-3.7 → -3, 3.7 → 3) Examples: ROUND TO NEAREST: values=3.14159, method="round", decimals=2 Result: 3.14 FLOOR (DOWN): values=3.14159, method="floor", decimals=2 Result: 3.14 CEIL (UP): values=3.14159, method="ceil", decimals=2 Result: 3.15 MULTIPLE VALUES: values=[3.14159, 2.71828], method="round", decimals=2 Result: [3.14, 2.72]""", annotations=ToolAnnotations( title="Advanced Rounding", readOnlyHint=True, idempotentHint=True, ), ) async def round_values( values: Annotated[ Union[float, List[float]], Field(description="Single value or list (e.g., 3.14159 or [3.14, 2.71])"), ], method: Annotated[ Literal["round", "floor", "ceil", "trunc"], Field(description="Rounding method") ] = "round", decimals: Annotated[int, Field(description="Number of decimal places", ge=0)] = 0, ) -> str: """Advanced rounding operations.""" try: is_single = isinstance(values, (int, float)) vals = [values] if is_single else values arr = np.array(vals, dtype=float) if method == "round": result = np.round(arr, decimals) elif method == "floor": result = np.floor(arr * 10**decimals) / 10**decimals elif method == "ceil": result = np.ceil(arr * 10**decimals) / 10**decimals elif method == "trunc": result = np.trunc(arr * 10**decimals) / 10**decimals else: raise ValueError(f"Unknown method: {method}") final_result = float(result[0]) if is_single else result.tolist() return format_result(final_result, {"method": method, "decimals": decimals}) except Exception as e: raise ValueError(f"Rounding operation failed: {str(e)}") @mcp.tool( name="convert_units", description="""Convert between angle units: degrees ↔ radians. Examples: DEGREES TO RADIANS: value=180, from_unit="degrees", to_unit="radians" Result: 3.14159... (π) RADIANS TO DEGREES: value=3.14159, from_unit="radians", to_unit="degrees" Result: 180 RIGHT ANGLE: value=90, from_unit="degrees", to_unit="radians" Result: 1.5708... (π/2)""", annotations=ToolAnnotations( title="Unit Converter", readOnlyHint=True, idempotentHint=True, ), ) async def convert_units( value: Annotated[float, Field(description="Value to convert (e.g., 180, 3.14159)")], from_unit: Annotated[Literal["degrees", "radians"], Field(description="Source unit")], to_unit: Annotated[Literal["degrees", "radians"], Field(description="Target unit")], ) -> str: """Convert between angle units.""" try: if from_unit == to_unit: result = value elif from_unit == "degrees" and to_unit == "radians": result = math.radians(value) elif from_unit == "radians" and to_unit == "degrees": result = math.degrees(value) else: raise ValueError(f"Unsupported conversion: {from_unit} to {to_unit}") return format_result( result, {"from_unit": from_unit, "to_unit": to_unit, "original_value": value} ) except Exception as e: raise ValueError(f"Unit conversion failed: {str(e)}")

Implementation Reference

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/apetta/vibe-math-mcp'

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