"""
计算器工具模块
提供基础数学计算功能的 MCP 工具。
"""
import math
from mcp.server.fastmcp import FastMCP
from ..models.responses import CalculationResult, BMIResult, StatisticsResult
def register_calculator_tools(mcp: FastMCP) -> None:
"""注册计算器相关的工具"""
@mcp.tool(title="Add Numbers", description="Add two numbers together")
def add(a: float, b: float) -> CalculationResult:
"""Add two numbers and return the result."""
result = a + b
return CalculationResult(
success=True,
result=result,
expression=f"{a} + {b}",
operation="addition"
)
@mcp.tool(title="Subtract Numbers", description="Subtract second number from first")
def subtract(a: float, b: float) -> CalculationResult:
"""Subtract b from a and return the result."""
result = a - b
return CalculationResult(
success=True,
result=result,
expression=f"{a} - {b}",
operation="subtraction"
)
@mcp.tool(title="Multiply Numbers", description="Multiply two numbers")
def multiply(a: float, b: float) -> CalculationResult:
"""Multiply two numbers and return the result."""
result = a * b
return CalculationResult(
success=True,
result=result,
expression=f"{a} * {b}",
operation="multiplication"
)
@mcp.tool(title="Divide Numbers", description="Divide first number by second")
def divide(a: float, b: float) -> CalculationResult:
"""Divide a by b and return the result."""
if b == 0:
raise ValueError("Cannot divide by zero")
result = a / b
return CalculationResult(
success=True,
result=result,
expression=f"{a} / {b}",
operation="division"
)
@mcp.tool(title="Calculate Power", description="Calculate a raised to the power of b")
def power(a: float, b: float) -> CalculationResult:
"""Calculate a raised to the power of b."""
result = a ** b
return CalculationResult(
success=True,
result=result,
expression=f"{a} ^ {b}",
operation="exponentiation"
)
@mcp.tool(title="Calculate Square Root", description="Calculate square root of a number")
def sqrt(x: float) -> CalculationResult:
"""Calculate the square root of x."""
if x < 0:
raise ValueError("Cannot calculate square root of negative number")
result = math.sqrt(x)
return CalculationResult(
success=True,
result=result,
expression=f"√{x}",
operation="square_root"
)
@mcp.tool(title="Calculate BMI", description="Calculate Body Mass Index")
def calculate_bmi(weight_kg: float, height_m: float) -> BMIResult:
"""
Calculate BMI (Body Mass Index) from weight and height.
Args:
weight_kg: Weight in kilograms
height_m: Height in meters
Returns:
BMI calculation result with structured data
"""
if weight_kg <= 0 or height_m <= 0:
raise ValueError("Weight and height must be positive numbers")
bmi = weight_kg / (height_m ** 2)
# Determine BMI category
if bmi < 18.5:
category = "Underweight"
elif bmi < 25:
category = "Normal weight"
elif bmi < 30:
category = "Overweight"
else:
category = "Obese"
return BMIResult(
success=True,
bmi=round(bmi, 2),
category=category,
weight_kg=weight_kg,
height_m=height_m
)
@mcp.tool(title="Calculate Percentage", description="Calculate percentage of a number")
def percentage(value: float, percentage: float) -> CalculationResult:
"""Calculate percentage of a value."""
result = (value * percentage) / 100
return CalculationResult(
success=True,
result=result,
expression=f"{percentage}% of {value}",
operation="percentage"
)
@mcp.tool(title="Calculate Average", description="Calculate average of a list of numbers")
def average(numbers: list[float]) -> StatisticsResult:
"""Calculate the average of a list of numbers."""
if not numbers:
raise ValueError("Cannot calculate average of empty list")
avg = sum(numbers) / len(numbers)
total = sum(numbers)
count = len(numbers)
minimum = min(numbers) if numbers else None
maximum = max(numbers) if numbers else None
return StatisticsResult(
success=True,
average=avg,
count=count,
sum=total,
minimum=minimum,
maximum=maximum
)