arcade-mcp/toolkits/math/arcade_math/tools/arithmetic.py
Eric Gustin 5228c75dc9
Add ToolMetadata to OSS toolkits (#776)
Resolves TOO-388


<!-- CURSOR_SUMMARY -->
---

> [!NOTE]
> **Low Risk**
> Primarily metadata/dependency additions with no changes to core tool
execution paths; risk is limited to potential packaging/import issues
from the new `arcade-mcp-server` dependency.
> 
> **Overview**
> Adds `ToolMetadata` to tool decorators across the Bright Data,
ClickHouse, MongoDB, Postgres, LinkedIn, Zendesk, and Math toolkits,
specifying *behavior* (read-only/idempotency/destructive/open-world)
and, where applicable, *service domain* classification.
> 
> Updates each toolkit package to depend on `arcade-mcp-server` (plus
local `uv` source wiring) and bumps toolkit versions accordingly; minor
`__all__` ordering tweaks in Math/Zendesk are included.
> 
> <sup>Written by [Cursor
Bugbot](https://cursor.com/dashboard?tab=bugbot) for commit
3bde3a061194e1d1b6a4e8a2ebd608b17984db4f. This will update automatically
on new commits. Configure
[here](https://cursor.com/dashboard?tab=bugbot).</sup>
<!-- /CURSOR_SUMMARY -->
2026-02-25 09:41:41 -08:00

161 lines
4 KiB
Python

import decimal
from decimal import Decimal
from typing import Annotated
from arcade_mcp_server.metadata import Behavior, ToolMetadata
from arcade_tdk import tool
decimal.getcontext().prec = 100
@tool(
metadata=ToolMetadata(
behavior=Behavior(
read_only=True,
destructive=False,
idempotent=True,
open_world=False,
),
),
)
def add(
a: Annotated[str, "The first number as a string"],
b: Annotated[str, "The second number as a string"],
) -> Annotated[str, "The sum of the two numbers as a string"]:
"""
Add two numbers together
"""
# Use Decimal for arbitrary precision
a_decimal = Decimal(a)
b_decimal = Decimal(b)
return str(a_decimal + b_decimal)
@tool(
metadata=ToolMetadata(
behavior=Behavior(
read_only=True,
destructive=False,
idempotent=True,
open_world=False,
),
),
)
def subtract(
a: Annotated[str, "The first number as a string"],
b: Annotated[str, "The second number as a string"],
) -> Annotated[str, "The difference of the two numbers as a string"]:
"""
Subtract two numbers
"""
# Use Decimal for arbitrary precision
a_decimal = Decimal(a)
b_decimal = Decimal(b)
return str(a_decimal - b_decimal)
@tool(
metadata=ToolMetadata(
behavior=Behavior(
read_only=True,
destructive=False,
idempotent=True,
open_world=False,
),
),
)
def multiply(
a: Annotated[str, "The first number as a string"],
b: Annotated[str, "The second number as a string"],
) -> Annotated[str, "The product of the two numbers as a string"]:
"""
Multiply two numbers together
"""
# Use Decimal for arbitrary precision
a_decimal = Decimal(a)
b_decimal = Decimal(b)
return str(a_decimal * b_decimal)
@tool(
metadata=ToolMetadata(
behavior=Behavior(
read_only=True,
destructive=False,
idempotent=True,
open_world=False,
),
),
)
def divide(
a: Annotated[str, "The first number as a string"],
b: Annotated[str, "The second number as a string"],
) -> Annotated[str, "The quotient of the two numbers as a string"]:
"""
Divide two numbers
"""
# Use Decimal for arbitrary precision
a_decimal = Decimal(a)
b_decimal = Decimal(b)
return str(a_decimal / b_decimal)
@tool(
metadata=ToolMetadata(
behavior=Behavior(
read_only=True,
destructive=False,
idempotent=True,
open_world=False,
),
),
)
def sum_list(
numbers: Annotated[list[str], "The list of numbers as strings"],
) -> Annotated[str, "The sum of the numbers in the list as a string"]:
"""
Sum all numbers in a list
"""
# Use Decimal for arbitrary precision
return str(sum([Decimal(n) for n in numbers]))
@tool(
metadata=ToolMetadata(
behavior=Behavior(
read_only=True,
destructive=False,
idempotent=True,
open_world=False,
),
),
)
def sum_range(
start: Annotated[str, "The start of the range to sum as a string"],
end: Annotated[str, "The end of the range to sum as a string"],
) -> Annotated[str, "The sum of the numbers in the list as a string"]:
"""
Sum all numbers from start through end
"""
return str(sum(list(range(int(start), int(end) + 1))))
@tool(
metadata=ToolMetadata(
behavior=Behavior(
read_only=True,
destructive=False,
idempotent=True,
open_world=False,
),
),
)
def mod(
a: Annotated[str, "The dividend as a string"],
b: Annotated[str, "The divisor as a string"],
) -> Annotated[str, "The remainder after dividing a by b as a string"]:
"""
Calculate the remainder (modulus) of one number divided by another
"""
# Use Decimal for arbitrary precision
return str(Decimal(a) % Decimal(b))