Skip to main content
Glama

Calculator MCP Server

by TechSuvam
calculator_server.py9.93 kB
#!/usr/bin/env python3 """ Calculator MCP Server A Model Context Protocol server that provides calculator tools. """ import asyncio import sys from typing import Any, Sequence try: from mcp.server import Server from mcp.server.stdio import stdio_server from mcp.types import Tool, TextContent except ImportError: print("Error: mcp package not found. Please install it with: pip install mcp", file=sys.stderr) sys.exit(1) # Create the MCP server instance server = Server("calculator-mcp-server") @server.list_tools() async def list_tools() -> list[Tool]: """List available calculator tools.""" return [ Tool( name="add", description="Add two or more numbers together", inputSchema={ "type": "object", "properties": { "numbers": { "type": "array", "items": {"type": "number"}, "description": "Array of numbers to add" } }, "required": ["numbers"] } ), Tool( name="subtract", description="Subtract numbers. Subtracts all subsequent numbers from the first", inputSchema={ "type": "object", "properties": { "numbers": { "type": "array", "items": {"type": "number"}, "description": "Array of numbers. First number is minuend, rest are subtrahends" } }, "required": ["numbers"] } ), Tool( name="multiply", description="Multiply two or more numbers together", inputSchema={ "type": "object", "properties": { "numbers": { "type": "array", "items": {"type": "number"}, "description": "Array of numbers to multiply" } }, "required": ["numbers"] } ), Tool( name="divide", description="Divide numbers. Divides first number by all subsequent numbers", inputSchema={ "type": "object", "properties": { "numbers": { "type": "array", "items": {"type": "number"}, "description": "Array of numbers. First number is dividend, rest are divisors" } }, "required": ["numbers"] } ), Tool( name="power", description="Raise a number to a power", inputSchema={ "type": "object", "properties": { "base": { "type": "number", "description": "The base number" }, "exponent": { "type": "number", "description": "The exponent" } }, "required": ["base", "exponent"] } ), Tool( name="sqrt", description="Calculate the square root of a number", inputSchema={ "type": "object", "properties": { "number": { "type": "number", "description": "The number to calculate square root of" } }, "required": ["number"] } ), Tool( name="evaluate", description="Evaluate a mathematical expression safely", inputSchema={ "type": "object", "properties": { "expression": { "type": "string", "description": "Mathematical expression to evaluate (e.g., '2 + 2 * 3')" } }, "required": ["expression"] } ) ] @server.call_tool() async def call_tool(name: str, arguments: dict[str, Any] | None) -> Sequence[TextContent]: """Handle tool calls.""" if arguments is None: arguments = {} try: if name == "add": numbers = arguments.get("numbers", []) if not numbers: return [TextContent(type="text", text="Error: No numbers provided")] result = sum(float(n) for n in numbers) return [TextContent(type="text", text=str(result))] elif name == "subtract": numbers = arguments.get("numbers", []) if not numbers: return [TextContent(type="text", text="Error: No numbers provided")] if len(numbers) < 2: return [TextContent(type="text", text="Error: At least two numbers required for subtraction")] result = float(numbers[0]) for n in numbers[1:]: result -= float(n) return [TextContent(type="text", text=str(result))] elif name == "multiply": numbers = arguments.get("numbers", []) if not numbers: return [TextContent(type="text", text="Error: No numbers provided")] result = 1 for n in numbers: result *= float(n) return [TextContent(type="text", text=str(result))] elif name == "divide": numbers = arguments.get("numbers", []) if not numbers: return [TextContent(type="text", text="Error: No numbers provided")] if len(numbers) < 2: return [TextContent(type="text", text="Error: At least two numbers required for division")] result = float(numbers[0]) for n in numbers[1:]: divisor = float(n) if divisor == 0: return [TextContent(type="text", text="Error: Division by zero")] result /= divisor return [TextContent(type="text", text=str(result))] elif name == "power": base = arguments.get("base") exponent = arguments.get("exponent") if base is None or exponent is None: return [TextContent(type="text", text="Error: Both base and exponent are required")] result = float(base) ** float(exponent) return [TextContent(type="text", text=str(result))] elif name == "sqrt": number = arguments.get("number") if number is None: return [TextContent(type="text", text="Error: Number is required")] num = float(number) if num < 0: return [TextContent(type="text", text="Error: Cannot calculate square root of negative number")] import math result = math.sqrt(num) return [TextContent(type="text", text=str(result))] elif name == "evaluate": expression = arguments.get("expression", "") if not expression: return [TextContent(type="text", text="Error: Expression is required")] # Safe evaluation using eval with limited globals and locals # Only allow basic math operations allowed_names = { "__builtins__": {}, "abs": abs, "round": round, "min": min, "max": max, "sum": sum, "pow": pow, } # Import math functions import math math_functions = { "sin": math.sin, "cos": math.cos, "tan": math.tan, "asin": math.asin, "acos": math.acos, "atan": math.atan, "sinh": math.sinh, "cosh": math.cosh, "tanh": math.tanh, "log": math.log, "log10": math.log10, "exp": math.exp, "sqrt": math.sqrt, "ceil": math.ceil, "floor": math.floor, "pi": math.pi, "e": math.e, } allowed_names.update(math_functions) try: # Compile to AST first for safety code = compile(expression, "<string>", "eval", flags=0) result = eval(code, allowed_names) return [TextContent(type="text", text=str(result))] except Exception as e: return [TextContent(type="text", text=f"Error evaluating expression: {str(e)}")] else: return [TextContent(type="text", text=f"Unknown tool: {name}")] except Exception as e: return [TextContent(type="text", text=f"Error: {str(e)}")] async def main(): """Main entry point for the MCP server.""" async with stdio_server() as (read_stream, write_stream): await server.run( read_stream, write_stream, server.create_initialization_options() ) if __name__ == "__main__": asyncio.run(main())

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/TechSuvam/MCP'

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