Skip to main content
Glama
chrishayuk

Physics MCP Server

by chrishayuk

Server Configuration

Describes the environment variables required to run the server.

NameRequiredDescriptionDefault
RAPIER_TIMEOUTNoRequest timeout for the Rapier service in seconds.30.0
PHYSICS_PROVIDERNoProvider selection: 'analytic' for built-in formula-based calculations or 'rapier' for rigid-body simulations requiring an external service.analytic
RAPIER_MAX_RETRIESNoMaximum number of retries for Rapier service requests.3
RAPIER_RETRY_DELAYNoDelay between retries for Rapier service requests in seconds.1.0
RAPIER_SERVICE_URLNoThe URL of the Rapier physics service. Defaults to the public service at https://rapier.chukai.io or http://localhost:9000 if running locally.https://rapier.chukai.io

Capabilities

Features and capabilities supported by this server

CapabilityDetails
tools
{
  "listChanged": true
}
resources
{
  "subscribe": false,
  "listChanged": true
}

Tools

Functions exposed to the LLM to take actions

NameDescription
calculate_projectile_motion

Calculate projectile motion trajectory using kinematic equations.

Computes the complete trajectory of a projectile launched at an angle, including maximum height, range, time of flight, and sample trajectory points. Perfect for ballistics, sports analysis, or educational demonstrations. Args: initial_velocity: Initial velocity in meters per second (m/s). Must be positive. angle_degrees: Launch angle in degrees from horizontal (0-90). 0° = horizontal, 45° = maximum range, 90° = straight up initial_height: Initial height above ground in meters. Default 0.0 (ground level). gravity: Gravitational acceleration in m/s². Default 9.81 (Earth surface). Use 1.62 for Moon, 3.71 for Mars, etc. Returns: ProjectileMotionResponse containing: - max_height: Maximum height reached (meters) - range: Horizontal distance traveled (meters) - time_of_flight: Total time in air (seconds) - trajectory_points: List of [x, y] sample points for plotting Tips for LLMs: - 45° gives maximum range on flat ground (no air resistance) - For R3F visualization: convert trajectory_points to 3D by adding z=0 - trajectory_points are evenly spaced in time (50 samples) - Air resistance is NOT modeled - this is ideal ballistic motion - Use for: cannon balls, baseballs, basketball shots, water fountains Example: # Calculate trajectory of a cannonball fired at 50 m/s at 30° result = await calculate_projectile_motion( initial_velocity=50.0, angle_degrees=30.0, initial_height=2.0 ) print(f"Range: {result.range:.1f}m, Max height: {result.max_height:.1f}m")
check_collision

Check if two moving spherical objects will collide.

Predicts whether two moving spheres will collide within a time window, and if so, calculates when and where the collision occurs. Uses analytic relative motion to find exact collision time (if any). Args: body1_position: Position of first object [x, y, z] in meters body1_velocity: Velocity of first object [x, y, z] in m/s body1_radius: Radius of first object in meters (must be positive) body2_position: Position of second object [x, y, z] in meters body2_velocity: Velocity of second object [x, y, z] in m/s body2_radius: Radius of second object in meters (must be positive) max_time: Maximum time to check in seconds. Default 10.0. Returns: CollisionCheckResponse containing: - will_collide: True if collision will occur - collision_time: Time until collision in seconds (if collision occurs) - collision_point: Approximate collision location [x, y, z] (if collision occurs) - impact_speed: Relative velocity at impact in m/s (if collision occurs) - closest_approach_distance: Minimum distance between objects - closest_approach_time: Time of closest approach Tips for LLMs: - Objects are modeled as spheres (point masses with radius) - Collision detection is exact for constant velocity motion - Returns earliest collision time if multiple intersections - If no collision, check closest_approach_distance to see how close they get - Use for: asteroid tracking, car crash prediction, sports ball interactions - For complex shapes or forces, use create_simulation instead Example: # Check if two cars will collide result = await check_collision( body1_position=[0.0, 0.0, 0.0], body1_velocity=[10.0, 0.0, 0.0], body1_radius=2.0, body2_position=[50.0, 1.0, 0.0], body2_velocity=[-8.0, 0.0, 0.0], body2_radius=2.0 ) if result.will_collide: print(f"Collision in {result.collision_time:.2f} seconds at {result.impact_speed:.1f} m/s")
calculate_force

Calculate force from mass and acceleration using Newton's Second Law (F = ma).

Computes the force vector required to produce a given acceleration on a mass. Fundamental for dynamics, engineering, and understanding motion. Args: mass: Mass in kilograms (must be positive) acceleration_x: X component of acceleration in m/s² acceleration_y: Y component of acceleration in m/s² acceleration_z: Z component of acceleration in m/s² Returns: ForceCalculationResponse containing: - force: Force vector [x, y, z] in Newtons - magnitude: Force magnitude in Newtons Tips for LLMs: - 1 Newton = force to accelerate 1 kg at 1 m/s² - On Earth, weight force = mass × 9.81 N (vertical) - Use magnitude to compare total force regardless of direction - Common accelerations: car braking ~10 m/s², elevator ~2 m/s² Example: # Force to accelerate a 1500kg car at 3 m/s² forward result = await calculate_force( mass=1500.0, acceleration_x=3.0, acceleration_y=0.0, acceleration_z=0.0 ) print(f"Required force: {result.magnitude:.0f} N")
calculate_kinetic_energy

Calculate kinetic energy from mass and velocity (KE = ½mv²).

Computes the energy of motion for a moving object. Energy is scalar (direction doesn't matter, only speed). Useful for collision analysis, vehicle safety, and understanding energy transfer. Args: mass: Mass in kilograms (must be positive) velocity_x: X component of velocity in m/s velocity_y: Y component of velocity in m/s velocity_z: Z component of velocity in m/s Returns: KineticEnergyResponse containing: - kinetic_energy: Energy in Joules (J) - speed: Velocity magnitude in m/s Tips for LLMs: - 1 Joule = 1 kg⋅m²/s² = energy to lift 102g by 1m on Earth - Kinetic energy doubles mass → doubles energy, doubles speed → 4× energy - Car at highway speed (~30 m/s, 1500 kg) ≈ 675,000 J - Use to compare impact severity or stopping distances Example: # Energy of a 0.145kg baseball at 40 m/s result = await calculate_kinetic_energy( mass=0.145, velocity_x=40.0, velocity_y=0.0, velocity_z=0.0 ) print(f"Kinetic energy: {result.kinetic_energy:.1f} J")
calculate_momentum

Calculate momentum from mass and velocity (p = mv).

Computes the momentum vector, which represents "quantity of motion." Momentum is conserved in collisions, making it crucial for analyzing impacts, explosions, and rocket propulsion. Args: mass: Mass in kilograms (must be positive) velocity_x: X component of velocity in m/s velocity_y: Y component of velocity in m/s velocity_z: Z component of velocity in m/s Returns: MomentumResponse containing: - momentum: Momentum vector [x, y, z] in kg⋅m/s - magnitude: Momentum magnitude in kg⋅m/s Tips for LLMs: - Momentum is a vector (has direction), unlike kinetic energy - Total momentum before collision = total momentum after (conservation) - Large mass × small velocity can equal small mass × large velocity - Use to analyze: collisions, recoil, rocket thrust Example: # Momentum of a 70kg person running at 5 m/s result = await calculate_momentum( mass=70.0, velocity_x=5.0, velocity_y=0.0, velocity_z=0.0 ) print(f"Momentum: {result.magnitude:.1f} kg⋅m/s")
calculate_potential_energy

Calculate gravitational potential energy.

Computes PE = mgh (mass × gravity × height). Also returns the equivalent velocity if the object falls from that height. Args: mass: Object mass in kilograms height: Height above reference point in meters gravity: Gravitational acceleration in m/s² (default 9.81 for Earth) Returns: Dict containing: - potential_energy: PE in Joules - equivalent_kinetic_velocity: Speed if dropped from height (m/s) Example - Object at 10m height: result = await calculate_potential_energy(mass=2.0, height=10.0) # PE = 196.2 J # Velocity if dropped = 14.0 m/s
calculate_work_power

Calculate work done by a force and optionally power.

Work is the dot product: W = F · d Power (if time given): P = W / t Args: force: Force vector [x, y, z] in Newtons (or JSON string) displacement: Displacement vector [x, y, z] in meters (or JSON string) time: Time taken in seconds (optional, for power calculation) Returns: Dict containing: - work: Work done in Joules - power: Power in Watts (if time provided, else None) Example - Pushing box 5m with 100N force: result = await calculate_work_power( force=[100, 0, 0], displacement=[5, 0, 0], time=10.0 ) # Work = 500 J, Power = 50 W
calculate_elastic_collision

Calculate final velocities after a 1D elastic collision.

Uses conservation of momentum and energy to solve for final velocities. Assumes perfectly elastic collision (no energy loss). Args: mass1: Mass of first object in kg velocity1: Initial velocity of first object in m/s (1D) mass2: Mass of second object in kg velocity2: Initial velocity of second object in m/s (1D) Returns: Dict containing: - final_velocity1: Final velocity of object 1 in m/s - final_velocity2: Final velocity of object 2 in m/s - initial_kinetic_energy: Total KE before (J) - final_kinetic_energy: Total KE after (J) - should equal initial - initial_momentum: Total momentum before (kg⋅m/s) - final_momentum: Total momentum after (kg⋅m/s) - should equal initial Example - Pool ball collision: result = await calculate_elastic_collision( mass1=0.17, # kg (pool ball) velocity1=2.0, # m/s (moving right) mass2=0.17, # kg (pool ball) velocity2=0.0 # m/s (stationary) ) # Result: ball 1 stops, ball 2 moves at 2.0 m/s
calculate_centripetal_force

Calculate centripetal force: F_c = m v² / r.

Force required to keep an object moving in a circle. Always points toward the center of the circular path. Args: mass: Mass in kg velocity: Speed (velocity magnitude) in m/s radius: Radius of circular path in meters Returns: Dict containing: - centripetal_force: F_c in Newtons - centripetal_acceleration: a_c in m/s² Tips for LLMs: - Not a new force - it's the net inward force (tension, friction, gravity) - Faster speed → much more force needed (v² relationship) - Tighter turn → more force needed - Use for: car turns, satellite orbits, centrifuges Example - Car turning: result = await calculate_centripetal_force( mass=1500, # kg velocity=20, # m/s (72 km/h) radius=50 # meter turn radius ) # F_c = 12000 N (provided by friction between tires and road)
calculate_orbital_period

Calculate orbital period: T = 2π√(r³/GM).

Kepler's Third Law for circular orbits. Period depends on orbital radius and central body mass. Args: orbital_radius: Orbital radius in meters (from center of central body) central_mass: Mass of central body in kg gravitational_constant: G in m³/(kg⋅s²) (default 6.674e-11) Returns: Dict containing: - period: Orbital period in seconds - orbital_velocity: v in m/s - period_hours: Period in hours (for convenience) - period_days: Period in days (for convenience) Tips for LLMs: - Higher orbit → longer period - More massive central body → shorter period - Earth: M = 5.972e24 kg, R = 6.371e6 m - Moon orbit: r ≈ 384,400 km, T ≈ 27.3 days - ISS orbit: r ≈ 6,771 km (altitude 400 km), T ≈ 90 minutes Example - ISS orbit: result = await calculate_orbital_period( orbital_radius=6.771e6, # meters central_mass=5.972e24 # Earth mass (kg) ) # T ≈ 5,558 seconds ≈ 92.6 minutes
calculate_banking_angle

Calculate ideal banking angle: θ = arctan(v² / (rg)).

For a banked curve, the ideal angle where no friction is needed to maintain the turn at a given speed. Args: velocity: Speed in m/s radius: Turn radius in meters gravity: Gravitational acceleration in m/s² (default 9.81) Returns: Dict containing: - angle_radians: Banking angle in radians - angle_degrees: Banking angle in degrees Tips for LLMs: - Faster speed → steeper banking angle - Tighter turn → steeper banking angle - NASCAR tracks banked ~30° for high-speed turns - At ideal angle, normal force provides all centripetal force Example - Highway exit ramp: result = await calculate_banking_angle( velocity=25, # m/s (90 km/h) radius=100 # meter radius turn ) # θ ≈ 32.5°
calculate_escape_velocity

Calculate escape velocity: v_escape = √(2GM/r).

Minimum speed needed to escape a celestial body's gravitational pull. Independent of the escaping object's mass. Args: mass: Mass of celestial body in kg radius: Radius of celestial body in meters gravitational_constant: G in m³/(kg⋅s²) (default 6.674e-11) Returns: Dict containing: - escape_velocity: v_escape in m/s - escape_velocity_kmh: v_escape in km/h (for convenience) Tips for LLMs: - Earth: v_escape ≈ 11,200 m/s (40,320 km/h) - Moon: v_escape ≈ 2,380 m/s - Sun: v_escape ≈ 617,500 m/s - Independent of escape direction or mass of escaping object Example - Earth escape velocity: result = await calculate_escape_velocity( mass=5.972e24, # Earth mass (kg) radius=6.371e6 # Earth radius (meters) ) # v_escape ≈ 11,186 m/s
analyze_circular_orbit

Analyze circular orbit at given altitude above planet surface.

Comprehensive orbital analysis combining period, velocity, and acceleration. Args: altitude: Altitude above surface in meters planet_mass: Planet mass in kg planet_radius: Planet radius in meters gravitational_constant: G in m³/(kg⋅s²) (default 6.674e-11) Returns: Dict containing: - orbital_radius: r from planet center in meters - orbital_velocity: v in m/s - period_seconds: Orbital period in seconds - period_minutes: Orbital period in minutes - centripetal_acceleration: a_c in m/s² Example - LEO satellite at 400km altitude: result = await analyze_circular_orbit( altitude=400000, # 400 km planet_mass=5.972e24, # Earth planet_radius=6.371e6 # Earth ) # v ≈ 7,670 m/s, T ≈ 92.6 min
calculate_inelastic_collision_3d

Calculate 3D collision with coefficient of restitution.

Models realistic collisions where some kinetic energy is lost. Coefficient of restitution (e) determines how much energy is retained. Args: mass1: Mass of object 1 in kg velocity1: Velocity of object 1 [x, y, z] in m/s (or JSON string) mass2: Mass of object 2 in kg velocity2: Velocity of object 2 [x, y, z] in m/s (or JSON string) coefficient_of_restitution: e (0.0 = perfectly inelastic, 1.0 = perfectly elastic) Returns: Dict containing: - final_velocity1: Final velocity [x, y, z] in m/s - final_velocity2: Final velocity [x, y, z] in m/s - initial_momentum: Total initial momentum [x, y, z] - final_momentum: Total final momentum [x, y, z] - initial_kinetic_energy: Total initial KE in Joules - final_kinetic_energy: Total final KE in Joules - energy_loss: Energy lost in Joules - energy_loss_percent: % of energy lost Coefficient of restitution values: - e = 0.0: Perfectly inelastic (clay, putty) - objects stick - e = 0.5: Very inelastic (wet clay) - e = 0.7: Moderately elastic (basketball) - e = 0.9: Highly elastic (Super Ball) - e = 1.0: Perfectly elastic (ideal, no energy loss) Tips for LLMs: - Momentum is always conserved (regardless of e) - Energy lost = (1 - e²) × initial KE in center-of-mass frame - Use e=1.0 for billiard balls, e=0.0 for car crashes Example - Car crash: result = await calculate_inelastic_collision_3d( mass1=1500, # kg velocity1=[20, 0, 0], # 20 m/s east mass2=1200, # kg velocity2=[-15, 0, 0], # 15 m/s west coefficient_of_restitution=0.1 # very inelastic ) # Massive energy loss, objects nearly stick together
calculate_elastic_collision_3d

Calculate 3D elastic collision (perfect energy conservation).

Special case of collision where no kinetic energy is lost (e = 1.0). Both momentum and energy are conserved. Args: mass1: Mass of object 1 in kg velocity1: Velocity of object 1 [x, y, z] in m/s (or JSON string) mass2: Mass of object 2 in kg velocity2: Velocity of object 2 [x, y, z] in m/s (or JSON string) Returns: Dict containing: - final_velocity1: Final velocity [x, y, z] in m/s - final_velocity2: Final velocity [x, y, z] in m/s - initial_momentum: Total momentum [x, y, z] - final_momentum: Total momentum [x, y, z] - initial_kinetic_energy: Total KE in Joules - final_kinetic_energy: Total KE in Joules Tips for LLMs: - Ideal approximation for billiard balls, Newton's cradle - Both momentum and energy conserved - Equal masses + head-on → velocities exchange - Use for educational examples, idealized systems Example - Pool balls: result = await calculate_elastic_collision_3d( mass1=0.17, # kg (pool ball) velocity1=[2, 0, 0], # 2 m/s mass2=0.17, # kg velocity2=[0, 0, 0] # stationary ) # Result: ball 1 stops, ball 2 moves at 2 m/s
check_energy_conservation

Verify conservation of energy in a physics process.

Checks whether total mechanical energy is conserved (or correctly dissipated). Useful for validating simulation results and understanding energy transfer. Args: initial_kinetic_energy: Initial KE in Joules final_kinetic_energy: Final KE in Joules initial_potential_energy: Initial PE in Joules final_potential_energy: Final PE in Joules expected_energy_loss: Expected energy loss (from friction, etc.) in Joules tolerance: Tolerance for conservation check (fraction, default 0.01 = 1%) Returns: Dict containing: - initial_total_energy: Initial total energy in Joules - final_total_energy: Final total energy in Joules - energy_difference: Energy difference in Joules - energy_difference_percent: % difference - is_conserved: Whether energy is conserved within tolerance - expected_loss: Expected energy loss in Joules - actual_loss: Actual energy loss in Joules Tips for LLMs: - In isolated systems, total energy is conserved - With friction/damping, expect energy loss - Small numerical errors are normal in simulations - Use to validate simulation accuracy Example - Bouncing ball with energy loss: result = await check_energy_conservation( initial_kinetic_energy=0, final_kinetic_energy=0, initial_potential_energy=10, # J (at 1m height) final_potential_energy=6.4, # J (bounced to 0.64m) expected_energy_loss=3.6, # 36% loss (e=0.8) tolerance=0.01 )
check_momentum_conservation

Verify conservation of momentum.

Checks whether total momentum is conserved in a collision or interaction. Momentum should be conserved in isolated systems (no external forces). Args: initial_momentum: Initial total momentum [x, y, z] in kg⋅m/s (or JSON string) final_momentum: Final total momentum [x, y, z] in kg⋅m/s (or JSON string) tolerance: Tolerance for conservation check (fraction, default 0.01 = 1%) Returns: Dict containing: - initial_momentum_magnitude: Initial |p| in kg⋅m/s - final_momentum_magnitude: Final |p| in kg⋅m/s - momentum_difference: Difference [x, y, z] - momentum_difference_magnitude: |Δp| - momentum_difference_percent: % difference - is_conserved: Whether momentum is conserved within tolerance Tips for LLMs: - Momentum is ALWAYS conserved in isolated systems - Vector quantity - direction matters - Use to validate collision calculations - External forces (friction, etc.) can change total momentum Example - Collision verification: result = await check_momentum_conservation( initial_momentum=[3000, 0, 0], # kg⋅m/s final_momentum=[2995, 5, 0], # slightly off tolerance=0.01 )
check_angular_momentum_conservation

Verify conservation of angular momentum.

Checks whether total angular momentum is conserved. Angular momentum is conserved when no external torques act on the system. Args: initial_angular_momentum: Initial L [x, y, z] in kg⋅m²/s (or JSON string) final_angular_momentum: Final L [x, y, z] in kg⋅m²/s (or JSON string) tolerance: Tolerance (fraction, default 0.01 = 1%) Returns: Dict containing: - initial_L_magnitude: Initial |L| in kg⋅m²/s - final_L_magnitude: Final |L| in kg⋅m²/s - L_difference: Difference [x, y, z] - L_difference_magnitude: |ΔL| - L_difference_percent: % difference - is_conserved: Whether L is conserved within tolerance Tips for LLMs: - Conserved when no external torques (isolated rotation) - Ice skater spinning: pull arms in → I decreases → ω increases (L constant) - Gyroscope: resists changes to L direction - Planets orbiting: L conserved → elliptical orbits Example - Figure skater: # Arms extended → Arms pulled in result = await check_angular_momentum_conservation( initial_angular_momentum=[0, 15, 0], # kg⋅m²/s final_angular_momentum=[0, 15.05, 0], tolerance=0.01 )
track_energy_dissipation

Track energy dissipation over a trajectory.

Analyzes how energy changes over time in a recorded trajectory. Useful for understanding damping, bounces, and energy loss mechanisms. Args: trajectory_data: Trajectory data dict with 'frames' field mass: Object mass in kg gravity: Gravitational acceleration in m/s² (default 9.81) reference_height: Reference height for PE in meters (default 0.0) Returns: Dict containing: - frames: Energy data for each frame (time, KE, PE, total E) - initial_total_energy: Initial total energy in Joules - final_total_energy: Final total energy in Joules - total_energy_loss: Total energy dissipated in Joules - total_energy_loss_percent: % of energy lost - average_power_dissipated: Average power in Watts (J/s) Tips for LLMs: - Use after record_trajectory or record_trajectory_with_events - Visualize energy vs time to see where energy is lost - Identifies bounces, friction effects, air resistance - Power = rate of energy dissipation Example - Bouncing ball energy analysis: traj = await record_trajectory_with_events(sim_id, "ball", 600) result = await track_energy_dissipation( trajectory_data=traj.model_dump(), mass=0.5, # 500g ball gravity=9.81 ) # See how energy decreases with each bounce
calculate_drag_force

Calculate drag force for an object moving through a fluid.

The drag force opposes motion and is given by: F_drag = 0.5 * ρ * v² * C_d * A Common drag coefficients: - Sphere: 0.47 - Streamlined shape: 0.04 - Flat plate (perpendicular): 1.28 - Human (standing): 1.0-1.3 - Car: 0.25-0.35 Args: velocity: Velocity vector [x, y, z] in m/s (or JSON string) cross_sectional_area: Area perpendicular to flow in m² fluid_density: Fluid density in kg/m³ (water=1000, air=1.225) drag_coefficient: Drag coefficient (default 0.47 for sphere) viscosity: Dynamic viscosity in Pa·s (water=1.002e-3, air=1.825e-5, oil=0.1). If not provided, estimated from fluid_density for Reynolds number calculation. Returns: Drag force vector, magnitude, and Reynolds number Example - Ball falling through water: result = await calculate_drag_force( velocity=[0, -5.0, 0], cross_sectional_area=0.00785, # π * (0.05m)² for 10cm diameter fluid_density=1000, # water drag_coefficient=0.47, viscosity=1.002e-3 # water viscosity for accurate Reynolds number ) # Returns upward drag force opposing downward motion Example - Ball falling through motor oil: result = await calculate_drag_force( velocity=[0, -2.0, 0], cross_sectional_area=0.00785, fluid_density=900, # oil drag_coefficient=0.47, viscosity=0.1 # motor oil is much more viscous )
calculate_buoyancy

Calculate buoyancy force using Archimedes' principle.

The buoyant force equals the weight of displaced fluid: F_b = ρ_fluid * V_submerged * g Args: volume: Object volume in m³ fluid_density: Fluid density in kg/m³ (water=1000, air=1.225) gravity: Gravitational acceleration in m/s² (default 9.81) submerged_fraction: Fraction submerged 0.0-1.0 (default 1.0 = fully submerged) Returns: Buoyant force (upward) and displaced mass Example - Checking if a 1kg ball will float: # 10cm diameter sphere: V = (4/3)πr³ = 0.000524 m³ result = await calculate_buoyancy( volume=0.000524, fluid_density=1000 # water ) # buoyant_force = 5.14 N # If weight (mg) < buoyant force, it floats # 1kg * 9.81 = 9.81 N > 5.14 N, so it sinks
calculate_terminal_velocity

Calculate terminal velocity when drag equals weight.

At terminal velocity, forces balance: F_drag = F_weight v_terminal = √(2mg / ρC_dA) Args: mass: Object mass in kg cross_sectional_area: Area perpendicular to fall direction in m² fluid_density: Fluid density in kg/m³ (air=1.225, water=1000) drag_coefficient: Drag coefficient (sphere=0.47, skydiver=1.0) gravity: Gravitational acceleration in m/s² (default 9.81) Returns: Terminal velocity, time to 95%, and drag force at terminal Example - Skydiver terminal velocity: result = await calculate_terminal_velocity( mass=70, # kg cross_sectional_area=0.7, # m² (belly-down position) fluid_density=1.225, # air drag_coefficient=1.0, # human ) # v_terminal ≈ 54 m/s (120 mph)
simulate_underwater_motion

Simulate underwater projectile motion with drag and buoyancy.

Uses numerical integration to simulate motion under: - Gravity (downward) - Buoyancy (upward, from displaced fluid) - Drag (opposes motion) Args: initial_velocity: Initial velocity [x, y, z] in m/s mass: Object mass in kg volume: Object volume in m³ cross_sectional_area: Cross-sectional area in m² fluid_density: Fluid density in kg/m³ (default 1000 for water) fluid_viscosity: Fluid viscosity in Pa·s (default 1.002e-3 for water) initial_position: Initial position [x, y, z] in m (default [0,0,0]) drag_coefficient: Drag coefficient (default 0.47 for sphere) gravity: Gravitational acceleration in m/s² (default 9.81) duration: Simulation duration in seconds (default 10.0) dt: Time step in seconds (default 0.01) Returns: Complete trajectory, final state, max depth, and total distance Example - Torpedo launch: result = await simulate_underwater_motion( initial_velocity=[20, 0, 0], # 20 m/s forward mass=100, # kg volume=0.05, # m³ cross_sectional_area=0.03, # m² fluid_density=1000, # water drag_coefficient=0.04, # streamlined duration=30.0 )
calculate_lift_force

Calculate lift force using: L = (1/2) ρ v² C_L A.

Based on Bernoulli's principle and wing aerodynamics. Args: velocity: Flow velocity in m/s wing_area: Wing area in m² lift_coefficient: Lift coefficient C_L (dimensionless) fluid_density: Fluid density in kg/m³ (air=1.225) Returns: Dict containing: - lift_force: Lift force in Newtons - dynamic_pressure: Dynamic pressure (q) in Pascals Example - Aircraft wing: result = await calculate_lift_force( velocity=70, # m/s (~250 km/h) wing_area=20.0, # m² lift_coefficient=1.2, fluid_density=1.225 )
calculate_magnus_force

Calculate Magnus force on a spinning ball.

The Magnus force is perpendicular to both velocity and spin axis. Causes curve balls in sports. Args: velocity: Ball velocity [x, y, z] in m/s (or JSON string) angular_velocity: Angular velocity [x, y, z] in rad/s (or JSON string) radius: Ball radius in meters fluid_density: Fluid density in kg/m³ (air=1.225) Returns: Dict containing: - magnus_force: Magnus force vector [x, y, z] in Newtons - magnus_force_magnitude: Force magnitude in Newtons - spin_rate: Spin rate (angular velocity magnitude) in rad/s Example - Soccer ball curve: result = await calculate_magnus_force( velocity=[20, 0, 0], # 20 m/s forward angular_velocity=[0, 0, 50], # 50 rad/s topspin radius=0.11, # Soccer ball fluid_density=1.225 )
calculate_bernoulli

Calculate Bernoulli's equation: P + (1/2)ρv² + ρgh = constant.

Energy conservation for flowing fluids. Args: pressure1: Pressure at point 1 in Pascals velocity1: Flow velocity at point 1 in m/s height1: Height at point 1 in meters velocity2: Flow velocity at point 2 in m/s (optional) height2: Height at point 2 in meters (optional) fluid_density: Fluid density in kg/m³ (default 1000 for water) gravity: Gravitational acceleration in m/s² (default 9.81) Returns: Dict containing: - total_pressure_1: Total pressure at point 1 - static_pressure_1: Static pressure component - dynamic_pressure_1: Dynamic pressure component - hydrostatic_pressure_1: Hydrostatic pressure component - pressure2: Pressure at point 2 (if velocity2/height2 given) Example - Water tank with outlet: result = await calculate_bernoulli( pressure1=101325, # Atmospheric at top velocity1=0, # Still water height1=10, # 10m height velocity2=14, # Exit velocity height2=0, # Ground level fluid_density=1000 )
calculate_pressure_at_depth

Calculate pressure at depth: P = P_atm + ρgh.

Hydrostatic pressure increases with depth. Args: depth: Depth below surface in meters fluid_density: Fluid density in kg/m³ (water=1000, seawater=1025) atmospheric_pressure: Pressure at surface in Pascals (default 101325) gravity: Gravitational acceleration in m/s² (default 9.81) Returns: Dict containing: - total_pressure: Total pressure in Pascals - gauge_pressure: Pressure above atmospheric in Pascals - pressure_atmospheres: Pressure in atmospheres (1 atm = 101325 Pa) Example - Scuba diving at 30m: result = await calculate_pressure_at_depth( depth=30, # meters fluid_density=1025, # seawater atmospheric_pressure=101325 ) # Result: ~4 atmospheres
calculate_reynolds_number

Calculate Reynolds number: Re = ρvL/μ.

Determines flow regime (laminar, transitional, turbulent). Args: velocity: Flow velocity in m/s characteristic_length: Characteristic length in meters (pipe diameter, etc.) fluid_density: Fluid density in kg/m³ dynamic_viscosity: Dynamic viscosity in Pa·s (water=0.001, air=1.8e-5) Returns: Dict containing: - reynolds_number: Re (dimensionless) - flow_regime: "laminar" (Re<2300), "transitional" (2300-4000), "turbulent" (Re>4000) Example - Water in pipe: result = await calculate_reynolds_number( velocity=2.0, # m/s characteristic_length=0.05, # 5cm diameter fluid_density=1000, # water dynamic_viscosity=0.001 ) # Re = 100,000 → turbulent
calculate_venturi_effect

Calculate Venturi effect (flow through constriction).

Uses continuity equation and Bernoulli's principle. Args: inlet_diameter: Inlet diameter in meters throat_diameter: Throat (constriction) diameter in meters inlet_velocity: Inlet velocity in m/s fluid_density: Fluid density in kg/m³ Returns: Dict containing: - throat_velocity: Velocity at throat in m/s - pressure_drop: Pressure drop from inlet to throat in Pascals - flow_rate: Volumetric flow rate in m³/s Example - Venturi meter: result = await calculate_venturi_effect( inlet_diameter=0.1, # 10 cm throat_diameter=0.05, # 5 cm inlet_velocity=2.0, # m/s fluid_density=1000 # water ) # throat_velocity = 8 m/s (4x area reduction)
calculate_acceleration_from_position

Calculate acceleration by numerical differentiation of position data.

Uses central differences for numerical differentiation: v[i] ≈ (r[i+1] - r[i-1]) / (2Δt) a[i] ≈ (v[i+1] - v[i-1]) / (2Δt) Args: times: Time values in seconds (or JSON string) positions: Position vectors [[x,y,z], ...] in meters (or JSON string) Returns: Dict containing: - velocities: Velocity vectors [[x,y,z], ...] in m/s - accelerations: Acceleration vectors [[x,y,z], ...] in m/s² - average_velocity: Average velocity [x,y,z] in m/s - average_acceleration: Average acceleration [x,y,z] in m/s² Example - Analyze recorded position data: result = await calculate_acceleration_from_position( times=[0, 1, 2, 3], positions=[[0,0,0], [5,0,0], [10,0,0], [15,0,0]] )
calculate_jerk

Calculate jerk (rate of change of acceleration).

Jerk = da/dt is important for comfort in vehicles and mechanical design. Args: times: Time values in seconds (or JSON string) accelerations: Acceleration vectors [[x,y,z], ...] in m/s² (or JSON string) Returns: Dict containing: - jerks: Jerk vectors [[x,y,z], ...] in m/s³ - average_jerk: Average jerk [x,y,z] in m/s³ - max_jerk_magnitude: Maximum jerk magnitude in m/s³ Example: result = await calculate_jerk( times=[0, 1, 2, 3], accelerations=[[0,0,0], [2,0,0], [4,0,0], [6,0,0]] ) # jerk_x ≈ 2 m/s³ (constant)
fit_trajectory

Fit polynomial to trajectory data.

Useful for smoothing noisy data or finding trajectory equations. Default fit_type="quadratic" fits parabolic trajectory (constant acceleration). Args: times: Time values in seconds (or JSON string) positions: Position vectors [[x,y,z], ...] in meters (or JSON string) fit_type: Polynomial type - "linear", "quadratic", or "cubic" (default "quadratic") Returns: Dict containing: - coefficients_x: Polynomial coefficients for x(t) - coefficients_y: Polynomial coefficients for y(t) - coefficients_z: Polynomial coefficients for z(t) - r_squared: R² goodness of fit (0-1) - predicted_positions: Fitted positions [[x,y,z], ...] Example - Projectile motion: result = await fit_trajectory( times=[0, 1, 2, 3], positions=[[0,0,0], [10,15,0], [20,20,0], [30,15,0]], fit_type="quadratic" ) # Fits x(t) = c0 + c1*t + c2*t²
generate_motion_graph

Generate motion graph data (position, velocity, acceleration vs time).

Calculates velocity and acceleration from position data and extracts the specified component for graphing. Args: times: Time values in seconds (or JSON string) positions: Position vectors [[x,y,z], ...] in meters (or JSON string) component: Which component to analyze - "x", "y", "z", or "magnitude" (default) Returns: Dict containing: - times: Time values - positions: Position values (selected component) - velocities: Velocity values (selected component) - accelerations: Acceleration values (selected component) - max_velocity: Maximum velocity magnitude - max_acceleration: Maximum acceleration magnitude - component: Which component was analyzed Example: result = await generate_motion_graph( times=[0, 1, 2, 3], positions=[[0,0,0], [5,0,0], [20,0,0], [45,0,0]], component="x" ) # Automatically calculates v and a
calculate_average_speed

Calculate average speed along a path.

Average speed = total distance / total time (Distance is path length, not displacement) Args: positions: Position vectors [[x,y,z], ...] in meters (or JSON string) times: Time values in seconds (or JSON string) Returns: Dict containing: - average_speed: Average speed in m/s - total_distance: Total path length in meters - total_time: Total elapsed time in seconds - displacement_magnitude: Straight-line displacement in meters - displacement: Displacement vector [x,y,z] in meters Example - Car on winding road: result = await calculate_average_speed( positions=[[0,0,0], [10,5,0], [20,10,0], [15,20,0]], times=[0, 10, 20, 30] )
calculate_instantaneous_velocity

Calculate instantaneous velocity at a specific time.

Uses interpolation if target_time is between data points, otherwise uses numerical differentiation. Args: positions: Position vectors [[x,y,z], ...] in meters (or JSON string) times: Time values in seconds (or JSON string) target_time: Time at which to calculate velocity in seconds Returns: Dict containing: - velocity: Velocity vector [x,y,z] in m/s - speed: Speed magnitude in m/s - interpolated: Whether interpolation was used - time: Target time (echo) Example: result = await calculate_instantaneous_velocity( positions=[[0,0,0], [3,4,0], [6,8,0]], times=[0, 1, 2], target_time=1.0 ) # speed = 5 m/s
calculate_projectile_with_drag

Calculate projectile motion including air resistance (drag).

Uses numerical integration (RK4) to solve motion equations with: - Quadratic drag force: F_drag = 0.5 * ρ * v² * Cd * A - Magnus force (spin effects): F_magnus = 0.5 * ρ * Cl * A * ω * r * v - Wind effects (constant wind vector) - Variable air density (altitude and temperature effects) This provides REALISTIC trajectories for sports balls, projectiles, and other objects moving through air or water. Compare with calculate_projectile_motion (no drag) to see dramatic differences! Common drag coefficients (Cd): - Sphere: 0.47 (default) - Baseball: 0.4 - Golf ball: 0.25 (dimples reduce drag) - Football (American): 0.05-0.15 (orientation-dependent) - Basketball: 0.55 - Soccer ball: 0.25 - Skydiver (belly-down): 1.0-1.3 - Streamlined car: 0.25-0.35 Args: initial_velocity: Launch velocity in m/s angle_degrees: Launch angle in degrees (0-90) mass: Object mass in kg cross_sectional_area: Cross-section perpendicular to motion in m² initial_height: Launch height in meters (default 0) drag_coefficient: Drag coefficient Cd (default 0.47 for sphere) fluid_density: Fluid density in kg/m³ (air=1.225, water=1000) gravity: Gravitational acceleration m/s² (default 9.81) time_step: Integration time step in seconds (default 0.01) max_time: Maximum simulation time in seconds (default 30) spin_rate: Spin rate in rad/s for Magnus force (default 0, no spin) spin_axis: Spin axis unit vector [x, y, z] (default [0, 0, 1] = vertical) wind_velocity: Wind velocity [vx, vy] in m/s (default [0, 0], no wind) altitude: Altitude above sea level in meters (default 0, affects air density) temperature: Air temperature in Celsius (default 15, affects air density) Returns: Dict containing: - max_height: Maximum altitude reached (m) - range: Horizontal distance traveled (m) - time_of_flight: Total flight time (s) - impact_velocity: Speed at landing (m/s) - impact_angle: Angle at landing (degrees below horizontal) - trajectory_points: [[x, y], ...] for plotting - energy_lost_to_drag: Energy dissipated by drag (J) - initial_kinetic_energy: Initial KE (J) - final_kinetic_energy: Final KE (J) - lateral_deflection: Lateral deflection from spin/wind (m) - magnus_force_max: Maximum Magnus force magnitude (N) - wind_drift: Total wind drift (m) - effective_air_density: Effective air density used (kg/m³) Example - Baseball curveball (2500 rpm backspin): result = await calculate_projectile_with_drag( initial_velocity=40.23, # 90 mph angle_degrees=10, mass=0.145, cross_sectional_area=0.0043, drag_coefficient=0.4, spin_rate=261.8, # 2500 rpm = 261.8 rad/s spin_axis=[0, 0, 1] # Backspin (vertical axis) ) # Backspin increases range and height! Example - Golf ball at altitude (Denver, 1600m): result = await calculate_projectile_with_drag( initial_velocity=70, angle_degrees=12, mass=0.0459, cross_sectional_area=0.00143, drag_coefficient=0.25, altitude=1600, # Denver elevation temperature=20 # Summer day ) # Less air resistance = longer drive! Example - Soccer free kick with wind: result = await calculate_projectile_with_drag( initial_velocity=25, angle_degrees=15, mass=0.43, cross_sectional_area=0.0388, drag_coefficient=0.25, wind_velocity=[5, 0], # 5 m/s tailwind spin_rate=50, # Sidespin for curve spin_axis=[0, 1, 0] # Horizontal axis ) # Wind drift + Magnus curve!
calculate_hookes_law

Calculate spring force using Hooke's Law: F = -kx.

The restoring force is proportional to displacement from equilibrium. Fundamental for springs, elastic materials, and simple harmonic motion. Args: spring_constant: Spring constant k in N/m (stiffness) displacement: Displacement from equilibrium in meters Returns: Dict containing: - force: Restoring force magnitude in Newtons - potential_energy: Elastic potential energy in Joules Tips for LLMs: - Stiffer spring → larger k → more force for same displacement - Potential energy stored in spring: PE = (1/2)kx² - Negative sign in F = -kx means force opposes displacement Example - Compressing a car spring: result = await calculate_hookes_law( spring_constant=10000, # N/m (stiff car spring) displacement=0.05 # 5cm compression ) # Force = 500 N, PE = 12.5 J
calculate_spring_mass_period

Calculate period of spring-mass system: T = 2π√(m/k).

Natural oscillation frequency of a mass attached to a spring. Independent of amplitude (for ideal springs). Args: mass: Mass in kg spring_constant: Spring constant k in N/m Returns: Dict containing: - period: T in seconds - frequency: f in Hz - angular_frequency: ω in rad/s Tips for LLMs: - Heavier mass → longer period (slower oscillation) - Stiffer spring → shorter period (faster oscillation) - ω = 2πf = √(k/m) Example - Mass on spring: result = await calculate_spring_mass_period( mass=0.5, # 500g mass spring_constant=20.0 # N/m ) # T ≈ 0.99s, f ≈ 1.01 Hz
calculate_simple_harmonic_motion

Calculate simple harmonic motion: x(t) = A cos(ωt + φ).

Position, velocity, and acceleration for sinusoidal oscillation. Models ideal springs, pendulums, and many other oscillating systems. Args: amplitude: Amplitude A in meters (maximum displacement) angular_frequency: ω in rad/s (ω = 2πf) time: Time t in seconds phase: Phase shift φ in radians (default 0) Returns: Dict containing: - position: x(t) in meters - velocity: v(t) = -Aω sin(ωt + φ) in m/s - acceleration: a(t) = -Aω² cos(ωt + φ) in m/s² Tips for LLMs: - Position and acceleration are 180° out of phase - Maximum velocity occurs at equilibrium (x = 0) - Maximum acceleration occurs at maximum displacement Example - Oscillating mass: result = await calculate_simple_harmonic_motion( amplitude=0.1, # 10cm amplitude angular_frequency=5.0, # rad/s time=1.0 # at t = 1s )
calculate_damped_oscillation

Calculate damped oscillation with friction/resistance.

Real oscillators lose energy over time due to damping (air resistance, friction). Three regimes: underdamped, critically damped, overdamped. Args: mass: Mass in kg spring_constant: k in N/m damping_coefficient: b in kg/s (damping strength) time: Time t in seconds initial_position: Initial position in meters (default 1.0) initial_velocity: Initial velocity in m/s (default 0.0) Returns: Dict containing: - position: x(t) in meters - velocity: v(t) in m/s - damping_ratio: ζ (zeta) = b/(2√(mk)) - regime: "underdamped", "critically_damped", or "overdamped" Damping regimes: - ζ < 1: Underdamped (oscillates, gradually decays) - ζ = 1: Critically damped (returns fastest without oscillating) - ζ > 1: Overdamped (slow return, no oscillation) Example - Car suspension: result = await calculate_damped_oscillation( mass=300, # kg (quarter car mass) spring_constant=20000, # N/m damping_coefficient=2000, # kg/s time=1.0 ) # Should be slightly underdamped for comfort
calculate_pendulum_period

Calculate pendulum period: T = 2π√(L/g).

Period of a simple pendulum depends only on length and gravity (for small amplitudes). Includes correction for large amplitudes. Args: length: Pendulum length in meters (pivot to center of mass) gravity: Gravitational acceleration in m/s² (default 9.81) amplitude_degrees: Amplitude in degrees (optional, for large angle correction) Returns: Dict containing: - period: T in seconds - frequency: f in Hz - angular_frequency: ω in rad/s - small_angle_approximation: Whether small angle formula was used Tips for LLMs: - Period independent of mass (Galileo's discovery) - Period independent of amplitude (for small angles < 15°) - Longer pendulum → longer period - Use for: clocks, playground swings, seismometers Example - Grandfather clock: result = await calculate_pendulum_period( length=0.994, # meters (for 2-second period) gravity=9.81 ) # T = 2.0 seconds
calculate_torque

Calculate torque from force and position: τ = r × F (cross product).

Torque is the rotational equivalent of force. It causes angular acceleration and depends on both the force magnitude and the distance from the pivot point. Args: force_x: X component of force in Newtons force_y: Y component of force in Newtons force_z: Z component of force in Newtons position_x: X component of position vector from pivot to force application (meters) position_y: Y component of position vector from pivot to force application (meters) position_z: Z component of position vector from pivot to force application (meters) Returns: Dict containing: - torque: Torque vector [x, y, z] in N⋅m - magnitude: Torque magnitude in N⋅m Tips for LLMs: - Torque direction follows right-hand rule (perpendicular to force and position) - Maximum torque when force is perpendicular to position vector - Zero torque when force is parallel to position vector - Use for: wrenches, door hinges, motors, gears Example - Opening a door: result = await calculate_torque( force_x=50.0, # Push perpendicular to door force_y=0.0, force_z=0.0, position_x=0.0, position_y=0.0, position_z=0.8 # 0.8m from hinge ) # Torque = 40 N⋅m
calculate_moment_of_inertia

Calculate moment of inertia for various shapes.

Moment of inertia (I) is the rotational equivalent of mass. It determines how difficult it is to change an object's rotation. Depends on both mass distribution and rotation axis. Args: shape: Shape type - "sphere", "solid_sphere", "hollow_sphere", "rod", "disk", "cylinder", "box" mass: Mass in kilograms radius: Radius for sphere/disk/cylinder (meters) length: Length for rod (meters) width: Width for box (meters) height: Height for box/cylinder (meters) depth: Depth for box (meters) axis: Rotation axis - "center", "end" (for rod), "x", "y", "z" (for box) Returns: Dict containing: - moment_of_inertia: I in kg⋅m² - shape: Shape type - axis: Rotation axis Common formulas: - Solid sphere (center): I = (2/5)mr² - Hollow sphere (center): I = (2/3)mr² - Rod (center): I = (1/12)mL² - Rod (end): I = (1/3)mL² - Disk (center): I = (1/2)mr² Example - Spinning wheel: result = await calculate_moment_of_inertia( shape="disk", mass=5.0, # 5kg wheel radius=0.3 # 30cm radius ) # I = 0.225 kg⋅m²
calculate_angular_momentum

Calculate angular momentum: L = I × ω.

Angular momentum is the rotational equivalent of linear momentum. It's conserved in the absence of external torques (like ice skater spinning). Args: moment_of_inertia: Moment of inertia in kg⋅m² angular_velocity_x: X component of angular velocity in rad/s angular_velocity_y: Y component of angular velocity in rad/s angular_velocity_z: Z component of angular velocity in rad/s Returns: Dict containing: - angular_momentum: L vector [x, y, z] in kg⋅m²/s - magnitude: L magnitude in kg⋅m²/s Tips for LLMs: - Angular momentum is conserved when no external torques act - Ice skater pulls arms in → I decreases → ω increases (L constant) - Gyroscopes resist changes in angular momentum direction Example - Spinning figure skater: # Arms extended: I = 3.0 kg⋅m², ω = 5 rad/s result = await calculate_angular_momentum( moment_of_inertia=3.0, angular_velocity_x=0.0, angular_velocity_y=5.0, angular_velocity_z=0.0 ) # L = 15 kg⋅m²/s (conserved when arms pulled in)
calculate_rotational_kinetic_energy

Calculate rotational kinetic energy: KE_rot = (1/2) I ω².

Energy of rotation. A spinning object has kinetic energy even if its center of mass is stationary. Args: moment_of_inertia: Moment of inertia in kg⋅m² angular_velocity: Angular velocity magnitude in rad/s Returns: Dict containing: - rotational_ke: Rotational kinetic energy in Joules Tips for LLMs: - Total KE = translational KE + rotational KE - Rolling object has both types of kinetic energy - Flywheel energy storage uses this principle Example - Car wheel at highway speed: result = await calculate_rotational_kinetic_energy( moment_of_inertia=0.5, # kg⋅m² angular_velocity=100.0 # rad/s (fast spinning) ) # KE_rot = 2500 J
calculate_angular_acceleration

Calculate angular acceleration: α = τ / I.

Angular acceleration is the rotational equivalent of linear acceleration. Determined by net torque and moment of inertia. Args: torque: Torque magnitude in N⋅m moment_of_inertia: Moment of inertia in kg⋅m² Returns: Dict containing: - angular_acceleration: α in rad/s² Tips for LLMs: - Rotational version of F = ma → τ = Iα - Larger I means slower angular acceleration for same torque - Use for: motor acceleration, spinning up flywheels Example - Motor accelerating a wheel: result = await calculate_angular_acceleration( torque=10.0, # N⋅m moment_of_inertia=0.5 # kg⋅m² ) # α = 20 rad/s²
check_force_balance

Check if forces are in equilibrium: ΣF = 0.

Verifies whether a system of forces is balanced (net force = 0). Essential for statics problems and structural analysis. Args: forces: List of force vectors [[x,y,z], ...] in Newtons (or JSON string) tolerance: Tolerance for equilibrium check (fraction, default 0.01) Returns: Dict containing: - net_force: Net force vector [x, y, z] in Newtons - net_force_magnitude: Net force magnitude in Newtons - is_balanced: Whether forces are in equilibrium - individual_magnitudes: Magnitude of each force Example - Bridge support forces: result = await check_force_balance( forces=[[0, 1000, 0], [0, 500, 0], [0, -1500, 0]], tolerance=0.01 ) # is_balanced = True if net force ≈ 0
check_torque_balance

Check if torques are in equilibrium: Στ = 0.

Verifies whether a system of torques is balanced (net torque = 0). Essential for rotational equilibrium and lever problems. Args: torques: List of torque vectors [[x,y,z], ...] in N⋅m (or JSON string) tolerance: Tolerance for equilibrium check (fraction, default 0.01) Returns: Dict containing: - net_torque: Net torque vector [x, y, z] in N⋅m - net_torque_magnitude: Net torque magnitude in N⋅m - is_balanced: Whether torques are in equilibrium - individual_magnitudes: Magnitude of each torque Example - Seesaw balance: result = await check_torque_balance( torques=[[0, 0, 100], [0, 0, -100]], tolerance=0.01 )
calculate_center_of_mass

Calculate center of mass for a system of point masses.

Formula: r_cm = Σ(m_i × r_i) / Σm_i Args: masses: List of masses in kg (or JSON string) positions: List of positions [[x,y,z], ...] in meters (or JSON string) Returns: Dict containing: - center_of_mass: Position [x, y, z] in meters - total_mass: Total system mass in kg Example - Three-mass system: result = await calculate_center_of_mass( masses=[1.0, 2.0, 3.0], positions=[[0,0,0], [1,0,0], [2,0,0]] ) # center_of_mass ≈ [1.5, 0, 0]
calculate_static_friction

Calculate maximum static friction force: f_s,max = μ_s × N.

Determines whether an object will slip under applied force. Args: normal_force: Normal force in Newtons coefficient_static_friction: Coefficient of static friction μ_s applied_force: Applied horizontal force in Newtons (optional) Returns: Dict containing: - max_static_friction: Maximum static friction in Newtons - will_slip: Whether object will slip (if applied_force provided) - friction_force: Actual friction force (if applied_force provided) Example - Box on floor: result = await calculate_static_friction( normal_force=100, coefficient_static_friction=0.5, applied_force=40 ) # will_slip = False (40N < 50N max)
calculate_normal_force

Calculate normal force on an inclined plane.

On an incline at angle θ: - N = mg cos(θ) + F_additional - Weight component perpendicular: mg cos(θ) - Weight component parallel: mg sin(θ) Args: mass: Object mass in kg gravity: Gravitational acceleration in m/s² (default 9.81) angle_degrees: Incline angle in degrees (0 = horizontal) additional_force: Additional perpendicular force in Newtons (optional) Returns: Dict containing: - normal_force: Normal force in Newtons - weight_component_perpendicular: Weight component ⊥ to surface - weight_component_parallel: Weight component ∥ to surface Example - Box on 30° ramp: result = await calculate_normal_force( mass=10.0, angle_degrees=30.0 ) # normal_force ≈ 84.9 N
check_equilibrium

Check complete static equilibrium: ΣF = 0 and Στ = 0.

For static equilibrium, both force and torque must be balanced. Args: forces: List of force vectors [[x,y,z], ...] in N (or JSON string) force_positions: Positions where forces applied [[x,y,z], ...] (or JSON string) pivot_point: Pivot point for torque calculation [x,y,z] (default [0,0,0]) tolerance: Tolerance for equilibrium check (default 0.01) Returns: Dict containing: - force_balanced: Whether ΣF = 0 - torque_balanced: Whether Στ = 0 - in_equilibrium: Whether system is in static equilibrium - net_force: Net force [x, y, z] in N - net_torque: Net torque [x, y, z] in N⋅m Example - Beam with two forces: result = await check_equilibrium( forces=[[0, 100, 0], [0, -100, 0]], force_positions=[[1, 0, 0], [2, 0, 0]] )
calculate_beam_reactions

Calculate reaction forces for a simply supported beam.

Uses moment equilibrium about supports to find reaction forces. Args: beam_length: Beam length in meters loads: Point loads in Newtons (downward positive) (or JSON string) load_positions: Positions of loads from left end in meters (or JSON string) Returns: Dict containing: - reaction_left: Reaction force at left support in Newtons - reaction_right: Reaction force at right support in Newtons - total_load: Total downward load in Newtons - is_balanced: Whether reactions balance loads Example - Beam with two loads: result = await calculate_beam_reactions( beam_length=10.0, loads=[1000, 500], load_positions=[3.0, 7.0] )
convert_unit
Convert a value from one unit to another. Supports 62 unit types across 16 categories: - Velocity: m/s, km/h, mph, ft/s, knots - Distance: m, km, mi, ft, yd, in - Mass: kg, g, lb, oz - Force: N, kN, lbf - Energy: J, kJ, cal, BTU, kWh - Power: W, kW, hp - Temperature: K, C, F - Angle: rad, deg - Pressure: Pa, kPa, bar, psi, atm - Area: m², km², ft², acre - Volume: m³, L, gal, ft³ - Time: s, min, hr, day - Acceleration: m/s², g, ft/s² - Torque: N·m, lb·ft, lb·in - Frequency: Hz, kHz, MHz, GHz - Data Size: B, KB, MB, GB Enables natural language queries like: - "Convert 60 mph to m/s" - "How fast is 100 km/h in mph?" - "Convert 10 kg to pounds" Args: value: The numeric value to convert from_unit: Source unit (e.g., 'mph', 'kg', 'J') to_unit: Target unit (e.g., 'm/s', 'lb', 'kWh') Returns: Dictionary with: - original_value: Input value - original_unit: Input unit - converted_value: Result value - converted_unit: Result unit - formatted: Human-readable string Examples: >>> convert_unit(100, 'm/s', 'mph') { "original_value": 100, "original_unit": "m/s", "converted_value": 223.694, "converted_unit": "mph", "formatted": "100 m/s = 223.694 mph" } >>> convert_unit(60, 'mph', 'km/h') { "original_value": 60, "original_unit": "mph", "converted_value": 96.56064, "converted_unit": "km/h", "formatted": "60 mph = 96.56 km/h" }
list_unit_conversions
List all supported unit conversions. Returns a dictionary mapping category names to lists of supported units. Returns: Dictionary with supported unit categories: - velocity: Speed units - distance: Length units - mass: Weight units - force: Force units - energy: Energy units - power: Power units - temperature: Temperature scales - angle: Angular units - pressure: Pressure units - area: Area units - volume: Volume units Example: >>> list_unit_conversions() { "velocity": ["m/s", "km/h", "mph", "ft/s", "knots"], "distance": ["m", "km", "mi", "ft", "yd", "in"], "mass": ["kg", "g", "lb", "oz"], ... }
create_simulation

Create a new physics simulation using Rapier engine.

Initializes a new rigid-body physics world with configurable gravity and timestep. Returns a simulation ID used for all subsequent operations. Args: gravity_x: X component of gravity vector (m/s²). Default 0.0 gravity_y: Y component of gravity vector (m/s²). Default -9.81 (Earth down) gravity_z: Z component of gravity vector (m/s²). Default 0.0 dimensions: 2 or 3 for 2D/3D simulation. Default 3. dt: Simulation timestep in seconds. Default 0.016 (60 FPS). Smaller = more accurate but slower, larger = faster but less stable integrator: Integration method. Options: "euler", "verlet", "rk4". Default "verlet". Returns: SimulationCreateResponse containing: - sim_id: Unique simulation identifier (use for all other sim calls) - config: Echo of the configuration used Tips for LLMs: - Keep simulation IDs in memory for the conversation session - Default gravity is Earth standard (9.81 m/s² down = -Y direction) - dt=0.016 ≈ 60 FPS, dt=0.008 ≈ 120 FPS (higher accuracy) - "verlet" integrator is good default (stable, energy-conserving) - Remember to destroy_simulation when done to free resources Requires: - Rapier provider must be configured (see config.py) - Rapier service must be running (see RAPIER_SERVICE.md) Example: # Create simulation with Earth gravity sim = await create_simulation( gravity_y=-9.81, dt=0.016 ) # Use sim.sim_id for add_body, step_simulation, etc.
add_rigid_body

Add a rigid body to an existing simulation.

Creates a new physics body (static, dynamic, or kinematic) with specified shape, mass, and initial conditions. Bodies interact via collisions. Args: sim_id: Simulation ID from create_simulation body_id: Unique identifier for this body (user-defined string) body_type: "static", "dynamic", or "kinematic" - static: Never moves (ground, walls) - dynamic: Affected by forces and collisions - kinematic: Moves but not affected by forces (scripted motion) shape: Collider shape: "box", "sphere", "capsule", "cylinder", "plane" size: Shape dimensions: - box: [width, height, depth] - sphere: [radius] - capsule: [half_height, radius] - cylinder: [half_height, radius] - plane: not needed (use normal/offset instead) mass: Mass in kilograms (for dynamic bodies). Default 1.0 normal: Normal vector [x, y, z] for plane shape. Default [0, 1, 0] (upward) offset: Offset along normal for plane. Default 0.0 position: Initial position [x, y, z]. Default [0, 0, 0] orientation: Initial orientation quaternion [x, y, z, w]. Default [0, 0, 0, 1] (identity) velocity: Initial linear velocity [x, y, z]. Default [0, 0, 0] angular_velocity: Initial angular velocity [x, y, z]. Default [0, 0, 0] restitution: Bounciness (0.0 = no bounce, 1.0 = perfect bounce). Default 0.5 friction: Surface friction (0.0 = ice, 1.0 = rubber). Default 0.5 is_sensor: If true, detects collisions but doesn't respond physically. Default false linear_damping: Linear velocity damping (0.0-1.0) - like air resistance. Default 0.0 angular_damping: Angular velocity damping (0.0-1.0) - like rotational friction. Default 0.0 drag_coefficient: Base drag coefficient (Cd) for orientation-dependent drag. Optional drag_area: Reference cross-sectional area (m²) for drag calculation. Optional drag_axis_ratios: Drag variation along body axes [x, y, z]. E.g., [1.0, 0.2, 1.0] for streamlined along Y. Optional fluid_density: Fluid density (kg/m³). Air=1.225, Water=1000. Default 1.225 Returns: body_id (echo of the input ID) Tips for LLMs: - Create ground FIRST: body_type="static", shape="plane", normal=[0, 1, 0] - Box size is full width/height/depth (not half-extents) - Sphere size is [radius] (array with one element) - Quaternions: identity = [0, 0, 0, 1] (no rotation) - Common restitution: steel=0.8, wood=0.5, clay=0.1 - Common friction: ice=0.05, wood=0.4, rubber=1.0 Example: # Add a ground plane await add_rigid_body( sim_id=sim_id, body_id="ground", body_type="static", shape="plane", normal=[0, 1, 0] ) # Add a bouncing ball await add_rigid_body( sim_id=sim_id, body_id="ball", body_type="dynamic", shape="sphere", size=[0.5], # radius = 0.5m mass=1.0, position=[0, 10, 0], restitution=0.7 ) # Add a falling box await add_rigid_body( sim_id=sim_id, body_id="box", body_type="dynamic", shape="box", size=[1.0, 1.0, 1.0], mass=10.0, position=[0.0, 5.0, 0.0] )
add_joint

Add a joint/constraint to connect two rigid bodies.

Joints allow you to constrain the motion between bodies: - FIXED: Rigid connection (glue objects together) - REVOLUTE: Hinge rotation around an axis (doors, pendulums) - SPHERICAL: Ball-and-socket rotation (ragdolls, gimbals) - PRISMATIC: Sliding along an axis (pistons, elevators) Args: sim_id: Simulation identifier joint: Joint definition with type and parameters Returns: joint_id: Unique identifier for the created joint Example - Simple Pendulum: # Create fixed anchor point add_rigid_body( sim_id=sim_id, body_id="anchor", body_type="static", shape="sphere", size=[0.05], position=[0.0, 5.0, 0.0], ) # Create pendulum bob add_rigid_body( sim_id=sim_id, body_id="bob", body_type="dynamic", shape="sphere", size=[0.1], mass=1.0, position=[0.0, 3.0, 0.0], ) # Connect with revolute joint (hinge) add_joint( sim_id=sim_id, joint=JointDefinition( id="pendulum_joint", joint_type="revolute", body_a="anchor", body_b="bob", anchor_a=[0.0, 0.0, 0.0], # Center of anchor anchor_b=[0.0, 0.1, 0.0], # Top of bob axis=[0.0, 0.0, 1.0], # Rotate around Z-axis ), )
step_simulation

Step the simulation forward in time.

Advances the physics simulation by running the integrator for N steps. Returns the complete state of all bodies after stepping. Args: sim_id: Simulation ID steps: Number of timesteps to simulate. Default 1. Example: steps=600 with dt=0.016 = 9.6 seconds of simulation dt: Optional timestep override (seconds). If None, uses config default. Returns: SimulationStepResponse containing: - sim_id: Simulation identifier - time: Current simulation time in seconds - bodies: List of all body states with positions, velocities, contacts Tips for LLMs: - Each body state includes position, orientation (quaternion), velocities - contacts array shows active collisions with impulse magnitudes - For real-time preview: steps=1, call repeatedly - For final result: steps=1000+, call once - Large step counts may timeout - limit to ~10,000 steps per call Example: # Simulate 10 seconds at 60 FPS result = await step_simulation( sim_id=sim_id, steps=600 # 600 steps × 0.016s = 9.6s ) for body in result.bodies: print(f"{body.id}: position={body.position}")
record_trajectory

Record the trajectory of a specific body over time.

Steps the simulation and records position/orientation/velocity at each timestep for one body. Perfect for generating animation data for R3F. Args: sim_id: Simulation ID body_id: ID of the body to track steps: Number of timesteps to record dt: Optional timestep override. If None, uses config default. Returns: TrajectoryResponse containing: - body_id: Tracked body identifier - frames: List of trajectory frames with time, position, orientation, velocity - total_time: Total simulated time in seconds - num_frames: Number of frames recorded Tips for LLMs: - Each frame has: time, position [x,y,z], orientation [x,y,z,w], velocity [x,y,z] - Frames are evenly spaced in time (every dt seconds) - Output is R3F-compatible: use position/orientation directly in Three.js - For 60 FPS video: record at dt=1/60 ≈ 0.0167 - Typical recording: 100-1000 frames (1.6-16 seconds at 60 FPS) Example: # Record 5 seconds of a falling ball traj = await record_trajectory( sim_id=sim_id, body_id="ball", steps=300 # 300 × 0.016 ≈ 5 seconds ) # Use traj.frames in React Three Fiber for animation
record_trajectory_with_events

Record trajectory and automatically detect collision and bounce events.

This is an enhanced version of record_trajectory that analyzes the motion and detects important events like bounces and collisions. Perfect for answering questions like "how many times did the ball bounce?" Args: sim_id: Simulation ID body_id: Body to track steps: Number of simulation steps to record dt: Optional custom timestep (overrides simulation default) detect_bounces: Whether to detect bounce events (default True) bounce_height_threshold: Maximum height to consider as "on ground" in meters (default 0.01) Returns: TrajectoryWithEventsResponse containing: - frames: Trajectory frames (positions, velocities) - bounces: Detected bounce events with energy loss - contact_events: Contact/collision events (future) Tips for LLMs: - Use this instead of record_trajectory when you need event detection - Bounces are detected from velocity reversals near the ground - Each bounce includes: time, position, speeds before/after, energy loss - Use `trajectory.bounces` to count or analyze bounces - Adjust bounce_height_threshold for different ground shapes Example: # Record ball bouncing and count bounces traj = await record_trajectory_with_events( sim_id=sim_id, body_id="ball", steps=600, detect_bounces=True, bounce_height_threshold=0.01 # 1cm threshold ) print(f"Detected {len(traj.bounces)} bounces") for bounce in traj.bounces: print(f"Bounce #{bounce.bounce_number} at t={bounce.time:.2f}s")
destroy_simulation

Destroy a simulation and free resources.

Cleanup when done with a simulation. Important for long-running servers to avoid memory leaks. Args: sim_id: Simulation ID to destroy Returns: Success message Tips for LLMs: - Always destroy simulations when conversation ends or changes topic - Rapier service keeps simulations in memory until explicitly destroyed - Good practice: destroy after recording trajectory or final state Example: await destroy_simulation(sim_id)

Prompts

Interactive templates invoked by user choice

NameDescription

No prompts

Resources

Contextual data attached and managed by the client

NameDescription

No resources

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/chrishayuk/chuk-mcp-physics'

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