Physics MCP Server
The Physics MCP Server transforms LLMs into a comprehensive physics engine with 79 specialized tools for calculations and simulations across classical mechanics, fluid dynamics, rotational motion, and rigid-body physics.
Core Physics Calculations: Projectile motion, forces (F=ma), kinetic/potential energy, momentum, work/power, and energy conservation verification—all computed instantly without external services.
Rigid-Body Simulations (Rapier Engine): Create 2D/3D physics worlds with multiple shapes (box, sphere, capsule, cylinder), material properties (friction, restitution, damping), joints (hinge, slider, spherical), and track multi-object interactions, collisions, stacking, and contact events with impulse magnitudes.
Advanced Projectile Physics: Realistic trajectories incorporating air resistance, Magnus force (spin effects), wind, altitude, and temperature, with orientation-dependent drag for tumbling objects.
Collision Physics: Predict 3D elastic and inelastic collisions with timing, impact location, energy loss quantification, and momentum transfer analysis.
Fluid Dynamics: Drag, buoyancy, terminal velocity, lift, Magnus force, Bernoulli's principle, pressure at depth, Reynolds number, Venturi effect, and underwater motion simulations.
Rotational Mechanics: Torque (τ = r × F), moment of inertia for various shapes, angular momentum (L = Iω), rotational kinetic energy (½Iω²), and angular acceleration.
Oscillations & Waves: Spring-mass systems (Hooke's law, periods, frequencies), simple harmonic motion, damped oscillations (underdamped, critically damped, overdamped), and pendulum calculations with large-angle corrections.
Circular Motion & Orbits: Centripetal force (mv²/r), orbital mechanics (Kepler's 3rd law), banking angles, escape velocity, and complete circular orbit analysis.
Statics & Equilibrium: Force balance (ΣF = 0), torque balance (Στ = 0), center of mass, static friction, normal force on inclines, beam reactions, and structural analysis.
Kinematics Analysis: Derive velocity, acceleration, and jerk from position data, trajectory fitting (linear, quadratic, cubic), motion graph generation, and average/instantaneous velocity calculations.
Conservation Laws: Verify energy, momentum, and angular momentum conservation, plus track energy dissipation over time.
Unit Conversions: Convert between 62+ unit types across 16 categories (velocity, distance, mass, force, energy, power, temperature, angle, pressure, area, volume, time, acceleration, torque, frequency, data size).
Visualization Integration: Generate detailed trajectory data (position, orientation, velocity) with automatic bounce and contact event detection for React Three Fiber, Remotion, and other 3D animation frameworks.
Use Cases: Education, game development, 3D visualization, engineering design, sports analytics, aerospace, marine engineering, film VFX, robotics, and scientific research including ML training data generation.
Provides specialized tools for generating physics-based trajectory and motion data tailored for React-based 3D frameworks such as React Three Fiber and Remotion.
Generates precise physical motion paths and trajectory arrays compatible with Three.js-based visualization engines for realistic 3D animations.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@Physics MCP Server Calculate the trajectory of a soccer ball with 15mph wind and Magnus force."
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
Physics MCP Server
Features: 🌀 Magnus Force • 💨 Wind Effects • 🏔️ Altitude • 🌡️ Temperature • 🔄 Tumbling Drag • 🎮 Rigid-Body Sims • 📊 515 Tests
A Model Context Protocol (MCP) server that brings comprehensive physics simulation and calculation capabilities to Large Language Models.
Transform your LLM into a physics engine! This MCP server provides 55 specialized tools spanning classical mechanics, fluid dynamics, rotational motion, and rigid-body simulations. Built for seamless integration with Claude, ChatGPT, and any MCP-compatible AI system.
📚 Table of Contents
Related MCP server: ucon-mcp
🌟 What is This?
Physics MCP Server enables LLMs to perform sophisticated physics calculations and simulations through a standardized protocol. Instead of hallucinating physics formulas or making calculation errors, LLMs can now:
Calculate precisely: Use validated physics formulas for exact results
Simulate realistically: Run rigid-body physics with the Rapier engine
Visualize motion: Generate trajectory data for React Three Fiber, Remotion, and other 3D frameworks
Teach interactively: Answer physics questions with real calculations, not memorized facts
Design intelligently: Analyze forces, collisions, and motion for engineering applications
Why MCP?
The Model Context Protocol provides a standardized way to extend LLM capabilities beyond text generation. This server implements MCP to give language models direct access to:
⚡ Instant physics calculations (projectile motion, forces, energy)
🎮 Rigid-body simulations (collisions, bounces, stacking)
📊 Motion analysis (trajectory fitting, kinematics, velocity profiles)
🌊 Fluid dynamics (drag, buoyancy, lift, Bernoulli)
🔄 Rotational mechanics (torque, angular momentum, gyroscopes)
⚖️ Static analysis (equilibrium, beam reactions, friction)
🔄 Unit conversions (62 unit types: velocity, distance, mass, time, acceleration, torque, frequency, data size, and more)
📦 What's Included
55 Physics Tools Across 10 Categories
Category | Tools | Description |
Basic Mechanics | 8 tools | Projectile motion, forces, energy, momentum, collisions |
Fluid Dynamics | 10 tools | Drag, buoyancy, terminal velocity, lift, Magnus force, Bernoulli |
Rotational Dynamics | 5 tools | Torque, moment of inertia, angular momentum, rotational KE |
Oscillations | 5 tools | Springs, pendulums, harmonic motion, damping |
Circular Motion | 5 tools | Centripetal force, orbits, banking angles, escape velocity |
Statics | 7 tools | Force balance, torque balance, friction, beam reactions |
Kinematics | 7 tools | Motion analysis, trajectory fitting, velocity calculations, projectile with drag |
Collisions | 2 tools | Elastic and inelastic 3D collisions with energy loss |
Conservation Laws | 4 tools | Energy, momentum, and angular momentum verification |
Unit Conversions | 2 tools | 62 unit types across 16 categories (velocity, distance, mass, time, acceleration, torque, frequency, data, etc.) |
Realistic vs Ideal Physics Comparison
See the dramatic difference when including real-world effects:
Sport | Scenario | Ideal (No Drag) | Realistic (With Enhancements) | Difference |
⚾ Baseball | 90 mph fastball | 87.5m | 52.3m (with drag) | -40% range |
⛳ Golf | Pro drive at sea level | 251m | 129m (with drag) | -49% range |
⛳ Golf | Same drive in Denver | 251m | 181m (drag + altitude) | -28% range |
⚽ Soccer | Free kick with wind | 25m straight | 26m + 5.6m curve (wind + spin) | Bends 5.6m! |
🎾 Tennis | Serve on hot day | 27m | 26.8m (less drag) | +2.3% vs cold |
💡 Key Insight: Real physics matters! Air resistance can reduce range by 20-70% depending on the sport.
Two Calculation Modes
Analytic Mode (Built-in, no setup)
Instant mathematical calculations
Perfect for education and quick answers
Exact solutions using physics formulas
Now includes: Advanced drag, spin (Magnus), wind, altitude effects
Simulation Mode (Requires Rapier service)
Full rigid-body dynamics
Complex multi-object interactions
Realistic material properties and constraints
🚀 Quick Start (30 seconds)
# Try it instantly with uvx (no installation needed)
uvx chuk-mcp-physics
# Or with the public Rapier service for simulations
RAPIER_SERVICE_URL=https://rapier.chukai.io uvx chuk-mcp-physics
# Or use the public hosted MCP server (no local installation)
# Add to Claude Desktop config with URL: https://physics.chukai.io/mcpFor Claude Desktop: Add to your config file:
Option 1: Public Hosted MCP Server (Easiest - No Installation)
{
"mcpServers": {
"physics": {
"command": "node",
"args": ["-e", "require('https').get('physics.chukai.io/mcp')"]
}
}
}Option 2: Local uvx (Recommended)
{
"mcpServers": {
"physics": {
"command": "uvx",
"args": ["chuk-mcp-physics"],
"env": {
"RAPIER_SERVICE_URL": "https://rapier.chukai.io"
}
}
}
}🎯 Use Cases
1. Interactive Physics Education
LLM as Physics Tutor
User: "If I throw a ball at 20 m/s at 45°, how far will it go?"
LLM: [calls calculate_projectile_motion]
"The ball will travel 40.8 meters and reach a maximum height of 10.2 meters..."
[generates visualization with trajectory points]Real-World Problem Solving
Students ask physics questions in natural language
LLM calculates exact answers using the MCP tools
Can generate trajectory plots, force diagrams, energy graphs
Interactive "what-if" scenarios: "What if gravity was half?"
2. Game Development & Prototyping
Ballistics Design
User: "I'm designing a cannon in my game. Initial velocity 50 m/s, 30° angle.
Will it clear a 15m wall at 80m distance?"
LLM: [calls calculate_projectile_motion]
"At 80m, the projectile is at 18.6m height - it WILL clear the wall.
It lands at 110.9m range."Collision Detection
User: "Two spaceships: Ship A at (0,0,0) moving at (10,0,0) m/s, Ship B at (100,5,0)
moving at (-8,0,0) m/s. Will they collide?"
LLM: [calls check_collision]
"Yes, collision in 5.3 seconds at position (53.0, 2.65, 0.0) with impact speed 18 m/s"Rapid Iteration
Test different launch angles, speeds, masses without coding
Verify collision logic before implementation
Generate realistic physics data for procedural content
3. 3D Visualization & Animation (React Three Fiber)
Automated Animation Data Generation
User: "Create a realistic basketball shot animation - 7m throw into 3m high basket"
LLM: [calls calculate_projectile_motion with solved angle]
[returns trajectory_points array]
"Here's the trajectory data for R3F. The ball needs 52° launch angle..."
<mesh position={interpolate(trajectory)}>
<sphereGeometry args={[0.12]} />
</mesh>Rigid-Body Simulations
User: "Simulate 10 boxes falling and stacking in a pile"
LLM: [calls create_simulation]
[calls add_rigid_body for ground + 10 boxes with random positions]
[calls record_trajectory for each box]
"Here are 10 trajectory arrays for your R3F scene, ready to use..."Use Cases:
Product visualizations (dropping phones, bouncing balls)
Architectural collapse simulations (building demolition previews)
Sports analytics visualizations (ball trajectories, collision analysis)
Sci-fi effects (asteroid fields, debris clouds)
4. Engineering & Design Analysis
Vehicle Crash Prediction
User: "Two cars: Car A (1500kg) at 30 m/s, Car B (1200kg) at 25 m/s approaching.
Distance 100m. When do they collide and what's the impact energy?"
LLM: [calls check_collision for timing]
[calls calculate_kinetic_energy for both cars]
[calls calculate_momentum for momentum analysis]
"Collision in 1.82 seconds. Total kinetic energy: 1,050,000 J..."Safety Analysis
Calculate impact forces for crash test scenarios
Predict collision times for autonomous vehicle planning
Analyze momentum transfer in industrial equipment
Structural Testing (with Rapier simulations)
Simulate falling objects hitting structures
Test load-bearing capacity under dynamic loads
Model chain reactions (domino effects)
5. Sports & Athletics
Realistic Ball Trajectories with Air Resistance
User: "How far does a 90 mph baseball fastball actually travel with air resistance?"
LLM: [calls calculate_projectile_with_drag with baseball parameters]
"With drag (realistic): 52.3m range
Without drag (vacuum): 87.5m range
Air resistance reduces range by 40%! Energy lost to drag: 89.2 J..."Golf Drive Analysis
User: "Pro golfer hits 70 m/s (155 mph) at 12° angle. How far with real air resistance?"
LLM: [calls calculate_projectile_with_drag with golf ball parameters]
"With drag: 129.4m (142 yards)
Without drag: 251.0m (274 yards)
Dimples reduce drag coefficient from 0.47 to 0.25 - saves ~50% range loss!"Basketball 3-Pointer
User: "What launch angle for a 7.5 m/s shot from 6.75m away (3-point line)?"
LLM: [calls calculate_projectile_with_drag iterating angles]
"With air resistance, optimal angle is 48° (high arc).
Range: 6.73m (close!), max height: 3.2m, flight time: 1.1s..."Shot Analysis Applications
Baseball: Pitch trajectories, drag reduces 90mph fastball range by 40%
Golf: Drive distance with dimpled ball (Cd=0.25 vs smooth ball Cd=0.47)
Basketball: Arc optimization for free throws and 3-pointers
Soccer: Penalty kick trajectories, minimal drag at short distances
Track & field: Javelin, shot put with realistic air resistance
Tennis: Serve and groundstroke trajectory analysis
6. Astrophysics & Space Exploration
Orbital Mechanics (Simplified)
User: "Two asteroids on collision course. A: 500m radius at (0,0,0) moving 15 km/s.
B: 300m radius at (100km, 2km, 0) moving -12 km/s. Impact prediction?"
LLM: [calls check_collision with appropriate units]
"Collision in 3.47 seconds at closest approach distance 650m.
They will NOT collide - miss distance is 150m..."Applications:
Asteroid impact prediction
Satellite collision avoidance
Debris field analysis
Launch trajectory planning (simplified cases)
7. Fluid Dynamics & Marine/Aerospace Engineering
Underwater Torpedo Simulation
User: "A torpedo is launched underwater at 20 m/s. It weighs 100kg, has a
streamlined shape (Cd=0.04), and cross-section of 0.03 m².
How far does it travel in 30 seconds?"
LLM: [calls simulate_underwater_motion]
"The torpedo travels 147.5 meters before drag and buoyancy slow it down.
Final velocity: 0.2 m/s. Maximum depth: 729.9 m..."Terminal Velocity & Drag Analysis
User: "What's the terminal velocity of a skydiver (70kg, 0.7m² area)?"
LLM: [calls calculate_terminal_velocity]
"Terminal velocity is 40 m/s (90 mph) in belly-down position.
Takes 12.2 seconds to reach 95% of terminal velocity..."Buoyancy & Float/Sink Predictions
User: "Will a 1kg steel ball (10cm diameter) float in water?"
LLM: [calls calculate_buoyancy]
"No, it will sink. Buoyant force is 5.14 N, but weight is 9.81 N.
The ball is denser than water..."Applications:
Marine engineering: Submarine drag, torpedo trajectories, underwater vehicles
Aerospace: Parachute descent, atmospheric re-entry, drag optimization
Sports science: Swimming efficiency, diving trajectories
Product design: Floatation devices, drag reduction, hydrodynamics
Environmental: Particle settling rates, pollutant dispersion
8. Film & VFX Pre-visualization
Stunt Planning
User: "Car jumps off 3m ramp at 25 m/s, 20° angle. How far does it fly and where does it land?"
LLM: [calls calculate_projectile_motion]
"Airtime: 1.75 seconds, landing at 42.9m horizontal distance,
impact speed 26.3 m/s. Recommend crashmat at 40-45m mark..."Destruction Sequences
Building collapses with rigid-body sim
Explosion debris trajectories
Vehicle stunts and crashes
Realistic object interactions
8. Military & Defense (Training/Education)
Ballistics Training
User: "Artillery shell: muzzle velocity 800 m/s, 45° elevation. Range and time of flight?"
LLM: [calls calculate_projectile_motion]
"Range: 65.3 km, flight time: 115.5 seconds, max altitude: 16.3 km"Collision Avoidance
Projectile trajectory analysis
Impact point prediction
Intercept course calculations
9. Robotics & Automation
Path Planning
User: "Robot arm needs to toss part into bin 2m away, 0.5m higher.
What velocity is needed?"
LLM: [reverse-calculates using projectile_motion multiple times]
"Minimum velocity: 4.7 m/s at 38° angle. Recommend 5.0 m/s for safety margin..."Collision Detection
Multi-robot coordination
Object catching/throwing
Assembly line optimization
10. Data Science & Research
Physics Simulations for ML Training Data
# Generate thousands of collision scenarios for ML model training
for i in range(10000):
result = await check_collision(random_params())
training_data.append({
'features': params,
'label': result.will_collide,
'impact_time': result.collision_time
})Use Cases:
Generate labeled physics data for ML models
Validate physics-informed neural networks
Test scientific hypotheses with rapid iteration
Monte Carlo simulations (vary parameters, aggregate results)
🚀 Real-World Example Workflows
Workflow 1: Basketball Shot Optimizer
1. User: "I'm 2m tall shooting from free-throw line (4.6m). Basket is 3.05m high.
What's the minimum velocity needed?"
2. LLM calls calculate_projectile_motion with varying velocities
- Try v=5 m/s → doesn't reach
- Try v=7 m/s → reaches
- Binary search finds minimum: v=6.2 m/s at 52° angle
3. LLM: "Minimum velocity is 6.2 m/s at 52° launch angle.
For comfortable margin, use 7.0 m/s (typical free throw speed).
Here's the trajectory visualization..."Workflow 2: Car Crash Investigation
1. User: "Analyze accident: Car A (1500kg) skid marks 30m, Car B (1200kg) skid marks 25m.
Coefficient of friction 0.7. What were impact speeds?"
2. LLM:
- Calculates deceleration from friction: a = μg = 0.7 × 9.81 = 6.87 m/s²
- Uses v² = 2ad to find velocities
- Calls calculate_kinetic_energy for both cars
- Calls calculate_momentum for momentum analysis
3. LLM: "Car A impact speed: ~20.3 m/s (45 mph), Car B: ~18.5 m/s (41 mph).
Total kinetic energy at impact: 513,000 J. Here's the force analysis..."Workflow 3: Game Level Design with Physics Simulation
1. User: "Create a Rube Goldberg machine: ball rolls down ramp, hits dominos,
dominos knock ball into basket"
2. LLM:
- Calls create_simulation(gravity_y=-9.81)
- Adds ground plane (static)
- Adds ramp (static, angled)
- Adds ball (dynamic, sphere, position at ramp top)
- Adds 10 dominos (dynamic boxes in a line)
- Adds basket (static)
- Calls step_simulation(steps=1000)
- Analyzes contacts to verify chain reaction
- Calls record_trajectory for each piece
3. LLM: "Simulation complete! Ball triggers all dominos successfully.
Here are the trajectories for R3F visualization.
Domino #3 falls at t=1.2s, domino #7 at t=2.1s..."Workflow 4: Satellite Collision Warning
1. User: "Satellite A: position (6700km, 0, 0), velocity (0, 7.5km/s, 0)
Satellite B: position (6650km, 50km, 0), velocity (0, 7.6km/s, 0.1km/s)
Collision risk?"
2. LLM:
- Calls check_collision with satellite data
- Analyzes closest approach
3. LLM: "No collision. Closest approach: 48.3 km at t=412 seconds.
Satellites are in similar orbits but safe separation.
Recommend: monitor as orbits may precess over time."🎨 Visualization Integration
React Three Fiber (R3F) Example
function PhysicsAnimation() {
const [trajectory, setTrajectory] = useState([]);
useEffect(() => {
// LLM generated this trajectory data via MCP
fetch('/api/mcp/record_trajectory', {
body: JSON.stringify({
sim_id: "sim_xyz",
body_id: "ball",
steps: 300
})
}).then(res => setTrajectory(res.frames));
}, []);
return (
<Canvas>
<AnimatedBall trajectory={trajectory} />
<Ground />
</Canvas>
);
}
function AnimatedBall({ trajectory }) {
const ref = useRef();
useFrame((state) => {
const t = state.clock.getElapsedTime();
const frame = trajectory[Math.floor(t / 0.016) % trajectory.length];
if (frame && ref.current) {
ref.current.position.fromArray(frame.position);
ref.current.quaternion.fromArray(frame.orientation);
}
});
return (
<mesh ref={ref}>
<sphereGeometry args={[0.5]} />
<meshStandardMaterial color="orange" />
</mesh>
);
}📊 Trajectory Data Format
All trajectory recordings follow a canonical schema for maximum interoperability with R3F, Remotion, Three.js, and other animation systems.
Schema Definition
interface Trajectory {
dt: number; // Time step between frames (seconds)
frames: Frame[]; // Ordered list of frames
meta: {
body_id: string; // Fully qualified: "rapier://sim-123/body-1"
total_time: number; // Total duration (seconds)
num_frames: number; // Frame count
};
}
interface Frame {
t: number; // Absolute time (seconds)
position: [number, number, number]; // [x, y, z] in meters
rotation: [number, number, number, number]; // Quaternion [x, y, z, w]
velocity?: [number, number, number]; // Optional: linear velocity (m/s)
angular_velocity?: [number, number, number]; // Optional: angular velocity (rad/s)
}JSON Example
{
"dt": 0.016,
"frames": [
{
"t": 0.0,
"position": [0, 1, 0],
"rotation": [0, 0, 0, 1],
"velocity": [0, 0, 0]
},
{
"t": 0.016,
"position": [0.1, 1.01, 0],
"rotation": [0, 0.01, 0, 0.9999],
"velocity": [6.25, 0.61, 0]
}
],
"meta": {
"body_id": "rapier://sim-abc123/ball",
"total_time": 4.8,
"num_frames": 300
}
}Usage in React Three Fiber
import { useRef } from "react";
import { useFrame } from "@react-three/fiber";
function AnimatedObject({ trajectory }) {
const ref = useRef();
useFrame((state) => {
const elapsed = state.clock.getElapsedTime();
const frameIdx = Math.floor(elapsed / trajectory.dt);
const frame = trajectory.frames[frameIdx % trajectory.frames.length];
if (frame && ref.current) {
ref.current.position.fromArray(frame.position);
ref.current.quaternion.fromArray(frame.rotation);
}
});
return (
<mesh ref={ref}>
<sphereGeometry args={[0.5]} />
<meshStandardMaterial color="orange" />
</mesh>
);
}Usage in Remotion
import { useCurrentFrame } from "remotion";
import { ThreeCanvas } from "@remotion/three";
export const PhysicsAnimation = ({ trajectory }) => {
const frame = useCurrentFrame();
const frameData = trajectory.frames[frame];
return (
<AbsoluteFill>
<ThreeCanvas>
<mesh position={frameData.position}>
<sphereGeometry />
</mesh>
</ThreeCanvas>
</AbsoluteFill>
);
};Design Notes
Quaternions for rotation: More compact and interpolation-friendly than Euler angles
Absolute time: Each frame has absolute time
t, making scrubbing easierConstant dt: Frames are evenly spaced, simplifying playback
Optional velocities: Include if needed for motion blur or physics visualization
Qualified body_id: Format is
rapier://sim-{id}/{body_id}for traceability
🛠️ Installation
Prerequisites
Python 3.11+
For simulations: Rapier service (see RAPIER_SERVICE.md)
Public service available at: https://rapier.chukai.io
Or run locally with Docker (see below)
Quick Start with uvx (Recommended)
The fastest way to try chuk-mcp-physics without installation:
# Run directly with uvx (no installation needed)
uvx chuk-mcp-physics
# With environment variables
uvx --with chuk-mcp-physics chuk-mcp-physicsInstallation Methods
Option 1: Install from PyPI (Recommended)
# Install globally
pip install chuk-mcp-physics
# Or with pipx (isolated environment)
pipx install chuk-mcp-physics
# Run the server
chuk-mcp-physics
# Or via python module
python -m chuk_mcp_physics.serverOption 2: Install from Source
# Clone repository (from your source location)
cd chuk-mcp-physics
# Install in development mode
make dev-install
# Run the server
chuk-mcp-physicsWith Claude Desktop
Add to your Claude Desktop config (~/Library/Application Support/Claude/claude_desktop_config.json on macOS):
Option 1: Using uvx (Recommended - No Installation Required)
{
"mcpServers": {
"physics": {
"command": "uvx",
"args": ["chuk-mcp-physics"],
"env": {
"PHYSICS_PROVIDER": "rapier",
"RAPIER_SERVICE_URL": "https://rapier.chukai.io"
}
}
}
}Option 2: Using Installed Package
{
"mcpServers": {
"physics": {
"command": "python",
"args": ["-m", "chuk_mcp_physics.server"],
"env": {
"PHYSICS_PROVIDER": "rapier",
"RAPIER_SERVICE_URL": "https://rapier.chukai.io"
}
}
}
}Option 3: Analytic Only (No External Service)
{
"mcpServers": {
"physics": {
"command": "uvx",
"args": ["chuk-mcp-physics"],
"env": {
"PHYSICS_PROVIDER": "analytic"
}
}
}
}📖 Available Tools
Tool Organization
Tools are organized into two tiers to help you choose the right abstraction:
1️⃣ Analytic Primitives (No External Service)
Best for: Quick calculations, education, simple scenarios
Direct formula-based calculations that return instant results:
Tool | What It Does | Example Use Case |
| Ballistic trajectory using kinematic equations | "How far does a cannonball go?" |
| Predict if two spheres will collide | "Will these asteroids hit?" |
| F = ma calculations | "What force accelerates this car?" |
| KE = ½mv² | "How much energy in this crash?" |
| p = mv | "What's the momentum transfer?" |
| PE = mgh | "What's the energy at height?" |
| Work (F·d) and power (W/t) | "How much work lifting this box?" |
| 1D elastic collision (conserves energy & momentum) | "Pool balls colliding?" |
| Air/water resistance (F = ½ρv²C_dA) | "What's the drag on this car?" |
| Will it float? (Archimedes) | "Does a steel ball float in water?" |
| Maximum fall speed | "How fast does a skydiver fall?" |
| Underwater trajectory with drag & buoyancy | "How far does a torpedo travel?" |
Characteristics:
⚡ Instant execution (< 1ms)
📦 No external dependencies
🎯 Exact mathematical solutions
✅ Always available (no service required)
Limitations:
Only spherical objects (for collisions)
No complex shapes
No multi-body interactions
No friction or material properties
2️⃣ Simulation Primitives (Requires Rapier Service)
Best for: Complex physics, multi-body dynamics, visualization data
Low-level building blocks for rigid-body simulations:
Tool | What It Does | When to Use |
| Initialize physics world | Start any simulation |
| Add objects (box, sphere, capsule, etc.) | Build scene |
| Advance time | Run physics |
| Capture motion for R3F/Remotion | Generate animation data |
| Cleanup resources | End simulation |
Characteristics:
🦀 Requires Rapier service
🔄 Stateful (track simulation ID)
🧩 Composable (combine for complex scenarios)
💪 Full rigid-body dynamics
Typical workflow:
# 1. Create world
sim = create_simulation(gravity_y=-9.81)
# 2. Add objects
add_rigid_body(sim.sim_id, "ground", type="static", shape="plane")
add_rigid_body(sim.sim_id, "ball", type="dynamic", shape="sphere",
radius=0.5, position=[0, 5, 0])
# 3. Run simulation
step_simulation(sim.sim_id, steps=300)
# 4. Record for visualization
trajectory = record_trajectory(sim.sim_id, "ball", steps=300)
# 5. Cleanup
destroy_simulation(sim.sim_id)📋 Complete Tool Reference
Basic Mechanics (8 tools)
Tool | Purpose | Example |
| Ballistic trajectories | "How far does a cannonball travel?" |
| Predict sphere collisions | "Will these asteroids hit?" |
| F = ma calculations | "What force accelerates this car?" |
| KE = ½mv² | "Energy in moving object?" |
| p = mv | "Momentum of moving object?" |
| PE = mgh | "Energy at height?" |
| Work (F·d) and power (W/t) | "Work done lifting object?" |
| 1D elastic collision | "Pool ball velocities after impact?" |
Fluid Dynamics (10 tools)
Tool | Purpose | Example |
| Air/water resistance | "Drag on car at speed?" |
| Will it float? (Archimedes) | "Does steel ball float?" |
| Maximum fall speed | "Skydiver terminal velocity?" |
| Underwater trajectory | "How far does torpedo travel?" |
| Aerodynamic lift | "Lift on aircraft wing?" |
| Force on spinning ball | "Why does curveball curve?" |
| Pressure in flowing fluid | "Pressure in pipe constriction?" |
| Hydrostatic pressure | "Pressure at 30m depth?" |
| Flow regime classification | "Is flow turbulent?" |
| Flow through constriction | "Velocity in throat?" |
Rotational Dynamics (5 tools)
Tool | Purpose | Example |
| τ = r × F (cross product) | "Torque from wrench?" |
| Rotational inertia | "MOI of spinning disk?" |
| L = Iω | "Angular momentum of wheel?" |
| Rotational KE = ½Iω² | "Energy in flywheel?" |
| α = τ/I | "How fast does it spin up?" |
Oscillations & Waves (5 tools)
Tool | Purpose | Example |
| Spring force F = -kx | "Force in compressed spring?" |
| Oscillation period | "How fast does mass oscillate?" |
| Position at time t | "Where is mass at t=2s?" |
| Motion with damping | "How quickly does it settle?" |
| Pendulum swing time | "Period of 1m pendulum?" |
Circular Motion & Orbits (5 tools)
Tool | Purpose | Example |
| F_c = mv²/r | "Force for circular motion?" |
| Kepler's 3rd law | "Satellite orbital period?" |
| Optimal curve angle | "Banking for highway curve?" |
| Escape from gravity | "Earth escape velocity?" |
| Complete orbital analysis | "Analyze ISS orbit?" |
Statics & Equilibrium (7 tools)
Tool | Purpose | Example |
| Verify ΣF = 0 | "Are forces balanced?" |
| Verify Στ = 0 | "Will seesaw balance?" |
| Balance point | "Where is center of mass?" |
| Max friction force | "Will object slip?" |
| Force on incline | "Normal force on ramp?" |
| Force + torque balance | "Is structure stable?" |
| Support forces | "Reaction forces on beam?" |
Kinematics Analysis (7 tools)
Tool | Purpose | Example |
| Derive from position data | "Acceleration from motion capture?" |
| Rate of acceleration change | "How jerky is motion?" |
| Find trajectory equation | "Fit parabola to data?" |
| Position/velocity/accel graphs | "Generate motion graphs?" |
| Speed along path | "Average speed on route?" |
| Velocity at exact time | "Speed at t=2.5s?" |
| Realistic projectile with air resistance | "How far does baseball actually go?" |
Advanced Collisions (2 tools)
Tool | Purpose | Example |
| 3D perfect collision | "Pool balls in 3D?" |
| 3D collision with energy loss | "Car crash analysis?" |
Conservation Laws (4 tools)
Tool | Purpose | Example |
| Verify energy conserved | "Is collision realistic?" |
| Verify momentum conserved | "Is momentum preserved?" |
| Verify L conserved | "Is rotation valid?" |
| Energy loss over time | "Where did energy go?" |
Unit Conversions (2 tools)
Tool | Purpose | Supported Units |
| Convert between units | Velocity: m/s, km/h, mph, ft/s, knotsDistance: m, km, mi, ft, yd, inMass: kg, g, lb, ozForce: N, kN, lbfEnergy: J, kJ, cal, BTU, kWhPower: W, kW, hpTemperature: K, C, FAngle: rad, degPressure: Pa, kPa, bar, psi, atmArea: m², km², ft², acreVolume: m³, L, gal, ft³Time: s, min, hr, dayAcceleration: m/s², g, ft/s²Torque: N·m, lb·ft, lb·inFrequency: Hz, kHz, MHz, GHzData Size: B, KB, MB, GB |
| Get all supported units | Returns complete list of conversions |
Examples:
# Natural language queries work perfectly
"Convert 60 mph to m/s" # → 26.82 m/s
"How fast is 100 km/h in mph?" # → 62.14 mph
"What's 10 kg in pounds?" # → 22.05 lb
"Convert 100 feet to meters" # → 30.48 m
"What's 98.6°F in Celsius?" # → 37°C
"Convert 3 g-force to m/s²" # → 29.42 m/s²
"What's 300 N·m in lb·ft?" # → 221.27 lb·ft
"Convert 1 hour to seconds" # → 3600 sFeatures:
⚡ Instant conversions (no external service needed)
🔄 Automatic indirect conversions (e.g., mph → km/h via m/s)
📐 70+ unit types across 16 categories
🎯 Perfect for natural language physics queries
🚀 Includes engineering units (torque, acceleration, frequency)
Common Drag Coefficients (Cd) Reference
For use with calculate_projectile_with_drag tool:
Object | Drag Coefficient (Cd) | Notes |
Sports Balls | ||
Baseball | 0.4 | Stitched surface |
Golf ball (dimpled) | 0.25 | Dimples reduce drag by ~50% |
Golf ball (smooth) | 0.47 | Without dimples (don't use!) |
Basketball | 0.55 | Large, textured surface |
Soccer ball | 0.25 | Modern, smooth panels |
Tennis ball | 0.55 | Fuzzy surface |
Football (American) | 0.05-0.15 | Highly streamlined, orientation-dependent |
Generic Shapes | ||
Sphere (smooth) | 0.47 | Default reference |
Flat plate (perpendicular) | 1.28 | Maximum drag |
Streamlined body | 0.04 | Teardrop/airfoil |
Cylinder (perpendicular) | 1.15 | Like a pole |
Vehicles | ||
Car (modern) | 0.25-0.35 | Aerodynamic design |
Truck | 0.6-0.9 | Boxy shape |
Bicycle + rider | 0.9 | Upright position |
Human Body | ||
Skydiver (belly-down) | 1.0-1.3 | Maximum drag |
Skydiver (head-down) | 0.7 | Streamlined |
Projectiles | ||
Bullet (supersonic) | 0.295 | Pointed nose |
Artillery shell | 0.15-0.25 | Streamlined |
Basic Usage Example:
# Baseball pitch with realistic drag
result = await calculate_projectile_with_drag(
initial_velocity=40.23, # 90 mph
angle_degrees=10,
mass=0.145,
cross_sectional_area=0.0043, # π × (0.037m)²
drag_coefficient=0.4 # Baseball Cd
)Advanced Projectile Features
The calculate_projectile_with_drag tool supports optional enhancements for ultra-realistic simulations:
🌀 Magnus Force (Spin Effects)
Spin creates a pressure differential that deflects the ball's path. Essential for:
Baseball: Curveballs (topspin drops), fastballs (backspin lifts)
Golf: Backspin increases carry, sidespin causes slices/hooks
Soccer: Bending free kicks around defensive walls
Tennis: Topspin brings ball down faster
# Baseball curveball with topspin
result = await calculate_projectile_with_drag(
initial_velocity=35,
angle_degrees=0,
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] # Topspin (negative z-axis)
)
# Returns lateral_deflection and magnus_force_maxSpin Parameters:
spin_rate: Rotation speed in rad/s (convert from RPM: rpm × 2π/60)spin_axis: Unit vector [x, y, z] indicating spin direction[0, 0, 1]= Backspin (lifts)[0, 0, -1]= Topspin (drops)[0, 1, 0]= Sidespin (hooks/slices)
💨 Wind Effects
Constant wind vector affects trajectory throughout flight:
# Soccer free kick with 5 m/s crosswind
result = await calculate_projectile_with_drag(
initial_velocity=28,
angle_degrees=12,
mass=0.43,
cross_sectional_area=0.0388,
drag_coefficient=0.25,
wind_velocity=[5.0, 0.0] # [horizontal, vertical] in m/s
)
# Returns wind_drift showing total deflectionWind Types:
Tailwind:
[+X, 0]- increases rangeHeadwind:
[-X, 0]- decreases rangeCrosswind:
[X, 0]- lateral deflectionUpdraft:
[0, +Y]- increases height and flight timeDowndraft:
[0, -Y]- decreases height
🏔️ Altitude & Temperature Effects
Air density varies with elevation and temperature, dramatically affecting drag:
# Golf drive in Denver (1600m elevation, 20°C)
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, # meters above sea level
temperature=20 # Celsius
)
# Returns effective_air_density showing actual density usedReal-World Impact:
Denver (1600m): ~10% longer drives than sea level
Hot day (+20°C): ~2-3% less drag than cold day
Everest Base Camp (5300m): ~50% less air density!
Air Density Formula:
ρ(h,T) = ρ₀ × exp(-Mgh/RT₀) × (T₀/T)Where:
ρ₀ = sea level density (1.225 kg/m³)
h = altitude (meters)
T = temperature (Kelvin)
M = molar mass of air (0.029 kg/mol)
g = gravity (9.81 m/s²)
R = gas constant (8.314 J/(mol·K))
🌟 Combined Effects Example
# Golf ball with ALL effects (spin + wind + altitude)
result = await calculate_projectile_with_drag(
initial_velocity=70,
angle_degrees=12,
mass=0.0459,
cross_sectional_area=0.00143,
drag_coefficient=0.25,
spin_rate=200, # Backspin
spin_axis=[0, 0, 1],
wind_velocity=[3, 0], # Tailwind
altitude=1000, # Moderate elevation
temperature=25 # Warm day
)
# All effects combine for maximum realism!See Examples:
examples/sports_projectiles_with_drag.py- Basic drag effectsexamples/advanced_projectile_effects.py- Magnus force, wind, altitude
🔄 Orientation-Dependent Drag (Rapier Simulations)
For tumbling objects like footballs, frisbees, and javelins, drag varies dramatically based on orientation. A football in a perfect spiral has 3-6× less drag than when tumbling end-over-end!
Available via Rapier rigid-body simulations using the add_rigid_body tool with orientation-dependent drag parameters.
How It Works
Objects moving through air experience drag that depends on their orientation:
Football spiral: Streamlined along flight path → low drag (~0.1 Cd)
Football tumbling: Broadside to airflow → high drag (~0.6 Cd)
Frisbee flat: Minimal cross-section → low drag (~0.08 Cd)
Frisbee tilted: Larger cross-section → higher drag
New add_rigid_body Parameters:
drag_coefficient: float # Base Cd value
drag_area: float # Reference cross-sectional area (m²)
drag_axis_ratios: [x, y, z] # Drag variation along body axes
fluid_density: float # Fluid density (air=1.225, water=1000)Example: Football Spiral vs Tumble
# Perfect spiral (low drag along Y-axis)
await add_rigid_body(
sim_id,
id="spiral",
shape="capsule",
size=[0.17, 0.28], # diameter, length
mass=0.42,
position=[0, 2, 0],
velocity=[vx, vy, 0],
angular_velocity=[0, 126, 0], # 20 rev/s spin
# Orientation-dependent drag
drag_coefficient=0.1,
drag_area=0.023, # End-on area
drag_axis_ratios=[1.0, 0.2, 1.0], # 5× less drag along Y
fluid_density=1.225
)
# Tumbling (higher drag, averaging all orientations)
await add_rigid_body(
sim_id,
id="tumble",
shape="capsule",
size=[0.17, 0.28],
mass=0.42,
position=[0, 2, 0],
velocity=[vx, vy, 0],
angular_velocity=[31.4, 0, 0], # Tumbling rotation
# Orientation-dependent drag
drag_coefficient=0.6, # Higher base Cd
drag_area=0.048, # Broadside area
drag_axis_ratios=[0.8, 1.0, 0.8], # Less streamlining
fluid_density=1.225
)Result: Spiral can travel 20-40% farther than tumble!
Common drag_axis_ratios Patterns
The drag_axis_ratios parameter specifies how drag varies along each body-local axis [X, Y, Z]:
Object | Ratios | Streamlined Axis | Use Case |
Football spiral |
| Y (length) | Perfect pass |
Javelin |
| Y (length) | Optimal flight |
Frisbee flat |
| Y (vertical) | Stable throw |
Sphere |
| None | Basketball, etc. |
Disc tumbling |
| Less variation | Wobbly throw |
Physical Meaning:
0.2= 20% of base drag along that axis (very streamlined)1.0= 100% of base drag (normal)1.5= 150% of base drag (higher resistance)
Real-World Examples
⚽ Football Throw (spiral vs tumble):
# Spiral: 45-50 yards typical
# Tumble: 30-35 yards (30-40% loss)🥏 Frisbee (stable vs wobbling):
# Stable (600 rpm spin): 60-80 meters
# Wobbling (slow spin): 30-40 meters (50% loss)🏹 Javelin (optimal vs poor technique):
# Optimal angle: 70-90 meters (Olympic level)
# Poor release: 40-50 meters (45% loss)Important Notes
⚠️ Requires Rapier Service: Orientation-dependent drag calculations are performed by the Rapier physics service (Rust implementation). The Python MCP server defines the API and passes parameters to Rapier.
🎯 When to Use:
Sports simulations (football, frisbee, discus)
Projectile accuracy (javelin, arrows, darts)
Aerospace applications (rocket tumbling, debris)
🔬 Physics: The drag force is calculated in the Rapier service using the body's current orientation (quaternion) to transform body-local drag coefficients into world-space drag forces.
Hybrid Drag Implementation: Rapier uses a hybrid approach to handle extreme drag cases:
Normal drag (ratio < 2.0): Force-based orientation-dependent drag with full anisotropic behavior
Extreme drag (ratio ≥ 2.0): Damping-based drag for stability when drag-to-weight ratio is very high
Automatically activates for objects like ping pong balls (high drag, low mass)
Prevents numerical instabilities while maintaining realistic energy dissipation
Logged as INFO when triggered:
"Body 'name' has extreme drag (ratio=X.XX), using damping"
Where drag_ratio = 0.5 * fluid_density * drag_coefficient * drag_area * v_typical^2 / (mass * g)
Measurement Notes:
When analyzing trajectories, use max(x_positions) instead of final_x to measure range. Rapier's solver may occasionally jitter backward slightly near ground impact, but this is a measurement artifact, not a physics error. The drag forces always oppose motion correctly.
See Example:
examples/tumbling_projectiles.py- Football, frisbee, and javelin orientation effects
✨ Phase 1 Features (Production Ready)
All Phase 1 features are complete, tested (98% coverage), and deployed to production!
Phase 1.1: Bounce Detection 🏀
Automatically detect and analyze bounces in ball trajectories with energy loss calculations.
What it does:
Detects bounce events from trajectory data (velocity reversals near ground)
Calculates energy loss percentage for each bounce
Provides before/after velocities and heights
Perfect for answering "how many bounces?" and "when does it stop?"
Tool: record_trajectory_with_events
Example:
# Record a bouncing ball
traj = await record_trajectory_with_events(
sim_id=sim_id,
body_id="ball",
steps=300,
detect_bounces=True,
bounce_height_threshold=0.01 # 1cm = "on ground"
)
print(f"Detected {len(traj.bounces)} bounces")
for bounce in traj.bounces:
print(f"Bounce #{bounce.bounce_number}:")
print(f" Time: {bounce.time:.2f}s")
print(f" Height: {bounce.height_at_bounce:.3f}m")
print(f" Energy loss: {bounce.energy_loss_percent:.1f}%")
print(f" Speed before: {bounce.speed_before:.2f} m/s")
print(f" Speed after: {bounce.speed_after:.2f} m/s")Output:
Detected 5 bounces
Bounce #1: Time: 1.43s, Height: 0.00m, Energy loss: 36.0%, Speed: 14.0→9.0 m/s
Bounce #2: Time: 2.51s, Height: 0.00m, Energy loss: 36.0%, Speed: 8.9→5.7 m/s
Bounce #3: Time: 3.23s, Height: 0.00m, Energy loss: 36.0%, Speed: 5.7→3.6 m/s
...Use Cases:
Sports analytics (basketball arc, tennis serve bounces)
Product testing (phone drop tests, durability simulations)
Game development (realistic ball physics)
Education (demonstrate energy conservation)
See: examples/06_bounce_detection.py for full demo
Phase 1.2: Contact Events 📊
Real-time collision tracking with detailed contact information from the physics engine.
What it does:
Tracks all contact events between bodies during simulation
Reports contact start, ongoing, and end events
Provides impulse magnitudes, normals, and relative velocities
Essential for collision analysis and force calculations
Included in: All trajectory recordings (record_trajectory, record_trajectory_with_events)
Contact Event Data:
ContactEvent(
time=1.43, # When contact occurred
body_a="ball", # First body
body_b="ground", # Second body
contact_point=[0.0, 0.05, 0.0], # World space position
normal=[0.0, 1.0, 0.0], # Contact normal (from A to B)
impulse_magnitude=14.2, # Collision impulse (N⋅s)
relative_velocity=[0.0, -14.0, 0.0], # Relative velocity
event_type="started" # "started", "ongoing", or "ended"
)Example:
traj = await record_trajectory(sim_id, "ball", steps=300)
# Analyze contacts
for event in traj.contact_events:
if event.event_type == "started":
print(f"Collision at t={event.time:.2f}s")
print(f" Bodies: {event.body_a} ↔ {event.body_b}")
print(f" Impulse: {event.impulse_magnitude:.1f} N⋅s")
print(f" Impact speed: {abs(event.relative_velocity[1]):.1f} m/s")Use Cases:
Collision analysis (car crashes, sports impacts)
Force calculations (derive forces from impulses)
Interaction tracking (which objects touched what)
VFX triggers (spark effects on collisions)
See: examples/07_contact_events.py for full demo
Phase 1.3: Joints & Constraints 🔗
Connect rigid bodies with realistic joints for complex mechanical systems.
What it does:
Create constraints between bodies (hinges, sliders, ball-and-socket, fixed)
Build complex systems (pendulums, chains, ragdolls, machinery)
Realistic mechanical motion (doors, wheels, linkages)
Perfect for simulating articulated structures
Tool: add_joint
Joint Types:
Type | Description | Example Uses |
FIXED | Rigid connection (glue) | Attach hat to head, weld joints |
REVOLUTE | Hinge rotation around axis | Doors, pendulums, wheels |
SPHERICAL | Ball-and-socket rotation | Ragdoll shoulders, gimbal mounts |
PRISMATIC | Sliding along axis | Pistons, elevators, sliders |
Example - Simple Pendulum:
# Create anchor point
await add_rigid_body(
sim_id=sim_id,
body_id="anchor",
body_type="static",
shape="sphere",
size=[0.05],
position=[0.0, 3.0, 0.0]
)
# Create pendulum bob
await add_rigid_body(
sim_id=sim_id,
body_id="bob",
body_type="dynamic",
shape="sphere",
size=[0.2],
mass=1.0,
position=[1.5, 1.5, 0.0] # Start displaced
)
# Connect with revolute joint (hinge)
await add_joint(
sim_id=sim_id,
joint=JointDefinition(
id="hinge",
joint_type=JointType.REVOLUTE,
body_a="anchor",
body_b="bob",
anchor_a=[0.0, 0.0, 0.0], # Center of anchor
anchor_b=[0.0, 0.2, 0.0], # Top of bob
axis=[0.0, 0.0, 1.0] # Rotate around Z-axis
)
)
# Simulate and see realistic pendulum motion!
traj = await record_trajectory(sim_id, "bob", steps=300)Example - Multi-Link Chain:
# Create anchor
await add_rigid_body(sim_id, "anchor", body_type="static", ...)
# Create 3 chain links
for i in range(3):
await add_rigid_body(
sim_id,
f"link{i}",
body_type="dynamic",
shape="box",
size=[0.1, 0.4, 0.1],
position=[0.0, 2.5 - i*0.5, 0.0]
)
# Connect with spherical joints (ball-and-socket)
await add_joint(sim_id, JointDefinition(
id="joint0",
joint_type=JointType.SPHERICAL,
body_a="anchor",
body_b="link0",
anchor_a=[0.0, 0.0, 0.0],
anchor_b=[0.0, 0.2, 0.0]
))
await add_joint(sim_id, JointDefinition(
id="joint1",
joint_type=JointType.SPHERICAL,
body_a="link0",
body_b="link1",
anchor_a=[0.0, -0.2, 0.0],
anchor_b=[0.0, 0.2, 0.0]
))
# ... and so onUse Cases:
Mechanical systems (engines, gears, levers)
Character animation (ragdolls, inverse kinematics)
Vehicle suspension (wheels, shocks)
Architectural simulations (doors, drawbridges)
See: examples/08_pendulum.py for full demo
Phase 1.4: Damping & Advanced Controls 🌬️
Realistic energy dissipation through linear and angular damping.
What it does:
Simulates air resistance (linear damping)
Simulates rotational friction (angular damping)
Makes simulations more realistic and stable
Perfect for settling physics and reducing "floaty" motion
Parameters: Added to add_rigid_body tool
Damping Parameters:
await add_rigid_body(
sim_id=sim_id,
body_id="damped_ball",
body_type="dynamic",
shape="sphere",
size=[0.5],
mass=1.0,
position=[0.0, 5.0, 0.0],
# Phase 1.4: Damping
linear_damping=0.5, # 0.0 (none) to 1.0 (high) - like air resistance
angular_damping=0.3 # 0.0 (none) to 1.0 (high) - like rotational friction
)Effect of Linear Damping:
0.0= No air resistance (vacuum physics)0.1-0.3= Light damping (tennis ball in air)0.5-0.7= Moderate damping (underwater motion)0.9+= Heavy damping (very viscous fluid)
Effect of Angular Damping:
0.0= Spins forever (vacuum)0.1-0.3= Realistic friction (rolling ball)0.5-0.7= High friction (rough surface)0.9+= Almost no rotation (sticky surface)
Comparison:
# Without damping - bounces forever
await add_rigid_body(..., linear_damping=0.0)
# Result: Ball bounces 20+ times, takes 30+ seconds to settle
# With damping - realistic settling
await add_rigid_body(..., linear_damping=0.5)
# Result: Ball bounces 5 times, settles in ~5 secondsUse Cases:
Realistic object motion (not "floaty" game physics)
Faster settling (less simulation time needed)
Underwater simulations (high damping)
Space simulations (zero damping)
See: examples/09_phase1_complete.py for all Phase 1 features combined
Phase 1.5: Fluid Dynamics 🌊
Analytical fluid calculations for drag, buoyancy, and underwater motion.
What it does:
Calculates drag forces (quadratic air/water resistance)
Computes buoyancy using Archimedes' principle
Determines terminal velocity for falling objects
Simulates underwater projectile motion with drag and buoyancy
Tools Available:
1. calculate_drag_force - Air/Water Resistance
Calculate the force opposing motion through a fluid.
# Ball falling through water
result = await calculate_drag_force(
velocity=[0, -5.0, 0], # 5 m/s downward
cross_sectional_area=0.00785, # π*r² for 10cm diameter
fluid_density=1000, # water (air=1.225)
drag_coefficient=0.47, # sphere (streamlined=0.04)
viscosity=1.002e-3 # optional: water viscosity for accurate Re
)
print(f"Drag force: {result['magnitude']:.1f} N (upward)")
print(f"Reynolds number: {result['reynolds_number']:.0f}")Common drag coefficients:
Sphere: 0.47
Streamlined (torpedo): 0.04
Flat plate: 1.28
Human (standing): 1.0-1.3
Car: 0.25-0.35
Optional viscosity parameter (for accurate Reynolds number):
Water at 20°C:
1.002e-3Pa·sAir at 20°C:
1.825e-5Pa·sMotor oil:
0.1Pa·sIf omitted, estimated from density (water-like if >100 kg/m³, else air-like)
2. calculate_buoyancy - Will it Float?
Determine buoyant force and whether objects float or sink.
# Check if 1kg steel ball floats
volume = (4/3) * π * (0.05)**3 # 10cm diameter sphere
result = await calculate_buoyancy(
volume=0.000524, # m³
fluid_density=1000 # water
)
weight = 1.0 * 9.81 # 9.81 N
buoyancy = result['buoyant_force'] # 5.14 N
# weight > buoyancy → SINKS3. calculate_terminal_velocity - Maximum Fall Speed
Calculate the speed where drag equals weight.
# Skydiver terminal velocity
result = await calculate_terminal_velocity(
mass=70, # kg
cross_sectional_area=0.7, # m² (belly-down)
fluid_density=1.225, # air
drag_coefficient=1.0 # human
)
print(f"Terminal velocity: {result['terminal_velocity']:.1f} m/s")
# Result: ~40 m/s (90 mph)
print(f"Time to 95%: {result['time_to_95_percent']:.1f}s")4. simulate_underwater_motion - Full Fluid Simulation
Simulate motion through fluids with drag and buoyancy forces.
# Torpedo launched underwater
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
)
print(f"Distance traveled: {result['total_distance']:.1f}m")
print(f"Final velocity: {result['final_velocity']}")
print(f"Max depth: {result['max_depth']:.1f}m")Use Cases:
Marine engineering: Torpedo trajectories, submarine drag
Aerospace: Skydiving, parachute descent, atmospheric re-entry
Sports: Swimming, diving, underwater ballistics
Product design: Drag optimization, floatation devices
Environmental: Particle settling, pollutant dispersion
Physics Models:
Quadratic drag: F_drag = 0.5 * ρ * v² * C_d * A
Buoyancy: F_b = ρ_fluid * V * g (Archimedes)
Terminal velocity: v_t = √(2mg / ρC_dA)
Numerical integration for complex underwater motion
See: examples/10_fluid_dynamics.py for comprehensive demonstrations
🎉 Phase 1 Complete Summary
Status: ✅ All features production-ready
Feature | Status | Tool | Coverage |
Bounce Detection | ✅ Shipped |
| 100% |
Contact Events | ✅ Shipped | All trajectory tools | 100% |
Joints & Constraints | ✅ Shipped |
| 100% |
Damping Controls | ✅ Shipped |
| 100% |
Fluid Dynamics | ✅ Shipped |
| 100% |
Test Coverage: 98% (350 tests passing)
Deployment:
🌐 MCP Server: https://physics.chukai.io/mcp
🦀 Rapier Service: https://rapier.chukai.io
Examples: See examples/06_bounce_detection.py through examples/10_fluid_dynamics.py
🚀 Phase 2 Features (Production Ready)
All Phase 2 features are complete, tested (98% coverage), and deployed to production!
Phase 2.1: Rotational Dynamics 🔄
Complete rotational motion calculations including torque, moment of inertia, angular momentum, and rotational kinetic energy.
Tools Available:
Tool | Description | Example Use |
| Calculate torque from force and position (τ = r × F) | "What torque does this wrench apply?" |
| Moment of inertia for common shapes (disk, sphere, rod, etc.) | "What's the rotational inertia?" |
| Angular momentum (L = Iω) | "How much rotational momentum?" |
| Rotational KE (½Iω²) | "Energy in spinning flywheel?" |
| Angular acceleration (α = τ/I) | "How fast does it spin up?" |
Example - Calculate Torque:
result = await calculate_torque(
force_x=50.0,
force_y=0.0,
force_z=0.0,
position_x=0.0,
position_y=0.0,
position_z=0.8 # 80cm wrench
)
# torque magnitude = 40 N⋅mUse Cases:
Mechanical engineering (gear systems, engines)
Robotics (joint torques, motor sizing)
Sports science (bat swings, golf clubs)
Aerospace (satellite attitude control)
Phase 2.2: Oscillations & Waves 🌊
Harmonic motion and spring systems with damping effects.
Tools Available:
Tool | Description | Example Use |
| Spring force and potential energy (F = -kx) | "How much force in compressed spring?" |
| Period and frequency of spring-mass system | "How fast does it oscillate?" |
| Position, velocity, acceleration at time t | "Where is the mass at t=2s?" |
| Damped harmonic motion (underdamped, critically damped, overdamped) | "How quickly does it settle?" |
| Period of simple pendulum | "How long is one swing?" |
Example - Spring-Mass System:
result = await calculate_spring_mass_period(
mass=0.5, # 500g mass
spring_constant=20.0 # N/m
)
# period ≈ 0.99s, frequency ≈ 1.01 HzUse Cases:
Mechanical design (suspension systems, vibration isolation)
Seismology (earthquake oscillations)
Electronics (LC circuits, resonance)
Horology (pendulum clocks)
Phase 2.3: Circular Motion & Orbits 🌍
Circular motion, orbital mechanics, and centripetal forces.
Tools Available:
Tool | Description | Example Use |
| Force required for circular motion | "What force keeps car on curve?" |
| Period and velocity for circular orbit | "How long is satellite orbit?" |
| Optimal banking for curved road | "What angle for this turn?" |
| Minimum velocity to escape gravity | "Can rocket escape Earth?" |
| Complete orbital analysis (altitude, period, velocity) | "Analyze ISS orbit" |
Example - Satellite Orbit:
result = await analyze_circular_orbit(
altitude=400000.0, # 400 km above surface
planet_mass=5.972e24, # Earth mass
planet_radius=6.371e6 # Earth radius
)
# orbital_velocity ≈ 7670 m/s
# period ≈ 5530 seconds (92 minutes)Use Cases:
Space missions (orbital calculations, satellite deployment)
Astrophysics (planetary motion, binary stars)
Transportation (highway curve design)
Amusement parks (loop-the-loop, centrifuges)
Phase 2.4: Advanced Collisions 💥
3D collision calculations with elastic and inelastic collisions.
Tools Available:
Tool | Description | Example Use |
| 3D elastic collision (energy conserved) | "Pool ball collisions in 3D" |
| 3D inelastic collision with restitution | "Car crash with energy loss" |
Example - Car Crash:
result = await calculate_inelastic_collision_3d(
mass1=1500.0,
velocity1=[20.0, 0.0, 0.0],
mass2=1200.0,
velocity2=[-15.0, 0.0, 0.0],
coefficient_of_restitution=0.0 # Perfectly inelastic
)
# final_velocity1 = [1.11, 0, 0]
# final_velocity2 = [1.11, 0, 0] # Stick together
# energy_loss > 0 (deformation energy)Phase 2.5: Conservation Laws ⚖️
Verify and track conservation of energy, momentum, and angular momentum.
Tools Available:
Tool | Description | Example Use |
| Verify total energy is conserved | "Is this collision realistic?" |
| Verify momentum is conserved | "Does this violate physics?" |
| Verify angular momentum conserved | "Is rotation energy conserved?" |
| Track energy loss over trajectory | "Where did the energy go?" |
Example - Validate Collision:
result = await check_energy_conservation(
initial_kinetic_energy=100.0,
final_kinetic_energy=50.0,
initial_potential_energy=0.0,
final_potential_energy=50.0
)
# is_conserved = True (100 = 50 + 50)
# energy_difference ≈ 0Phase 2.6: Statics & Equilibrium ⚖️
Static equilibrium analysis for structures and forces.
Tools Available:
Tool | Description | Example Use |
| Verify ΣF = 0 (force equilibrium) | "Are these forces balanced?" |
| Verify Στ = 0 (torque equilibrium) | "Will this seesaw balance?" |
| Find center of mass for system | "Where is the balance point?" |
| Maximum friction force, will object slip? | "Will box slide down ramp?" |
| Normal force on inclined plane | "What force on ramp?" |
| Complete equilibrium check (force + torque) | "Is structure stable?" |
| Reaction forces for simply supported beam | "What are support forces?" |
Example - Beam Analysis:
result = await calculate_beam_reactions(
beam_length=10.0,
loads=[1000, 500], # Two point loads
load_positions=[3.0, 7.0] # Positions along beam
)
# reaction_left = 800 N
# reaction_right = 700 N
# is_balanced = TrueUse Cases:
Structural engineering (bridges, buildings)
Mechanical design (levers, balances)
Architecture (load analysis)
Safety analysis (stability checks)
Phase 2.7: Kinematics Analysis 📊
Analyze motion data to extract velocities, accelerations, and trajectories.
Tools Available:
Tool | Description | Example Use |
| Derive velocity and acceleration from position data | "Analyze motion capture data" |
| Calculate jerk (rate of change of acceleration) | "How jerky is this motion?" |
| Fit polynomial to trajectory (linear, quadratic, cubic) | "Find trajectory equation" |
| Generate position/velocity/acceleration graphs | "Visualize kinematics" |
| Average speed along path | "What's average speed?" |
| Velocity at specific time with interpolation | "Speed at exact moment?" |
Example - Motion Analysis:
result = await calculate_acceleration_from_position(
times=[0, 1, 2, 3, 4],
positions=[[0,0,0], [5,0,0], [10,0,0], [15,0,0], [20,0,0]]
)
# velocities = [[5,0,0], [5,0,0], ...] # Constant 5 m/s
# average_acceleration ≈ [0,0,0] # No accelerationUse Cases:
Motion capture analysis (sports, biomechanics)
Robotics (trajectory planning, motion smoothness)
Autonomous vehicles (trajectory optimization)
Scientific research (particle tracking)
Phase 2.8: Advanced Fluid Dynamics 💨
Extended fluid calculations including lift, Magnus force, Bernoulli, and viscous flow.
Tools Available:
Tool | Description | Example Use |
| Aerodynamic lift (L = ½ρv²C_LA) | "What lift on wing?" |
| Force on spinning ball | "Why does curveball curve?" |
| Bernoulli's equation for flowing fluids | "Pressure in pipe constriction?" |
| Hydrostatic pressure | "Pressure at 30m depth?" |
| Flow regime (laminar/turbulent) | "Is flow turbulent?" |
| Flow through constriction | "Velocity in throat?" |
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 # air
)
# lift_force ≈ 73,500 NUse Cases:
Aerospace engineering (aircraft design, aerodynamics)
Marine engineering (hull design, submarine motion)
Sports science (ball trajectories, swimming efficiency)
HVAC design (airflow optimization)
🎉 Phase 2 Complete Summary
Status: ✅ All features production-ready
Feature Area | Tools | Coverage |
Rotational Dynamics | 5 tools | 100% |
Oscillations | 5 tools | 100% |
Circular Motion | 5 tools | 100% |
Advanced Collisions | 2 tools | 100% |
Conservation Laws | 4 tools | 100% |
Statics | 7 tools | 100% |
Kinematics Analysis | 6 tools | 100% |
Advanced Fluids | 6 tools | 100% |
Total Tools: 79 tools across all categories Test Coverage: 98% overall (350 tests passing)
Next Up: Phase 3 - Performance Optimization & Visualization
Batch simulation API for ML training data
Parameter sweep utilities
Enhanced visualization exports
Performance profiling and optimization
🎓 Example Conversations
Projectile Motion
User: A golf ball is hit at 70 m/s at 15 degrees. How far does it go and what's the flight time?
LLM: [calls calculate_projectile_motion(70, 15)]
Range ≈ 249.7 m
Time of flight ≈ 3.694 s
Maximum height ≈ 16.73 m
Here are 50 trajectory points for visualization...User: What angle gives maximum range for a cannonball fired at 100 m/s?
LLM: [calls calculate_projectile_motion multiple times with different angles]
The optimal angle is 45°, which gives:
- Maximum range: 1019.4 m
- Flight time: 14.4 s
- Peak height: 254.8 mCollision Detection
User: Two asteroids: one at (0,0,0) moving at 1000 m/s in x direction,
another at (50000, 100, 0) moving at -800 m/s in x. Will they collide?
LLM: [calls check_collision with both objects]
Yes, they will collide!
- Collision time: ~27.8 seconds
- Impact location: (27,778, 100, 0)
- Impact speed: 1,800 m/s
- This would be a devastating impact given the closing speed.User: Two cars 500m apart, one at 60 mph, other at 45 mph heading toward each other.
When do they collide?
LLM: [calls check_collision]
Collision in 10.7 seconds at position 250m from car 1's starting point.
Combined approach speed is 105 mph (46.9 m/s).Force & Energy Calculations
User: What force is needed to accelerate a 1500 kg car at 3 m/s²?
LLM: [calls calculate_force(1500, 3)]
Force required: 4,500 N (Newtons)
This is about 1,011 pounds of force.User: What's the kinetic energy of a 2000 kg car at 30 m/s (about 67 mph)?
LLM: [calls calculate_kinetic_energy(2000, 30)]
Kinetic energy: 900,000 J (Joules)
That's 900 kJ or 0.25 kWh of energy.
For perspective, this is why car crashes at highway speeds are so dangerous.Momentum Analysis
User: Calculate momentum of a 70 kg runner at 10 m/s
LLM: [calls calculate_momentum(70, 10)]
Momentum: 700 kg⋅m/s
Direction: same as velocity vectorComplex Multi-Step Problems
User: I'm designing a water fountain. Water shoots up at 15 m/s.
How high does it go and when does it come back down?
LLM: [calls calculate_projectile_motion(15, 90)]
The water will:
- Rise to maximum height: 11.47 m
- Take 1.53 seconds to reach peak
- Return to ground level after 3.06 seconds total
- Have the same 15 m/s speed when it lands (just downward)User: A basketball player shoots from 2m high at 7 m/s toward a hoop
3.05m high and 4.6m away. What angles work?
LLM: [calls calculate_projectile_motion with various angles]
Two possible angles work:
1. Low arc: 38° (faster, flatter shot)
2. High arc: 52° (slower, higher shot)
Most players use 50-55° for better chance of going in.Rigid Body Simulations
User: Create a simulation of a ball dropping from 10 meters and bouncing
LLM: [calls create_simulation(gravity_y=-9.81)]
[calls add_rigid_body for ground plane (static)]
[calls add_rigid_body for ball (dynamic, sphere, position=(0,10,0))]
[calls record_trajectory(steps=200)]
Simulation complete! The ball:
- Hits ground at t=1.43s with velocity 14.0 m/s
- Bounces to 7.5m (with restitution=0.8)
- Makes 5 bounces before settling
Here's the full trajectory data for R3F visualization...User: Simulate 5 boxes stacked, then another box hits them from the side
LLM: [calls create_simulation]
[calls add_rigid_body for ground]
[calls add_rigid_body 5 times for stacked boxes]
[calls add_rigid_body for projectile box with velocity]
[calls step_simulation(300)]
[calls record_trajectory for each box]
The collision causes a realistic toppling effect!
Boxes 1-2 fall left, boxes 3-5 scatter right.
Peak chaos at t=0.8s. All settled by t=3.2s.
Full trajectory data ready for 3D visualization...💡 Try These Prompts
Copy and paste these into your LLM chat to see the physics tools in action:
Projectile Motion
A golf ball is hit at 70 m/s at 15 degrees. How far does it go and what's the flight time?What angle gives maximum range for a cannonball fired at 100 m/s?If I throw a javelin at 28 m/s from 2 meters high, what angle gives maximum distance?A basketball player shoots from 2m high at 7 m/s toward a hoop 3.05m high and 4.6m away. What angles work?
Collision Detection
Two cars 500m apart, one at 60 mph, other at 45 mph heading toward each other. When do they collide?Two asteroids: one at (0,0,0) moving at 1000 m/s in x direction, another at (50000, 100, 0) moving at -800 m/s in x. Will they collide?Spaceship A at (10000,0,0) moving at (-50,0,0) m/s, spaceship B at (-10000,100,0) moving at (45,0,0) m/s. Collision check?
Force, Energy & Momentum
What force is needed to accelerate a 1500 kg car at 3 m/s²?What's the kinetic energy of a 2000 kg car traveling at 30 m/s?Calculate the momentum of a 70 kg runner sprinting at 10 m/sHow much energy does a 0.145 kg baseball have when pitched at 45 m/s?
Real-World Applications
I'm designing a water fountain. Water shoots up at 15 m/s. How high does it go?A cannon on a 50 meter cliff fires horizontally at 200 m/s. How far from the base does the projectile land?Two cars crash: Car A (1500kg) at 30 m/s, Car B (1200kg) at 25 m/s. What's the total kinetic energy at impact?
Simulations (Requires Rapier Service)
Create a simulation of a ball dropping from 10 meters height and bouncing on the groundSimulate 5 boxes stacked on top of each other, then have another box hit them from the sideCreate a Newton's cradle with 5 spheres and record their motionSimulate a sphere rolling down a 30-degree ramp
📝 Example Scripts
The examples/ directory contains working demonstration scripts:
Ready to Run (No External Services Required)
These examples use the built-in analytic provider and work immediately:
00_quick_start.py- Quick demo of all 5 analytic tools01_simple_projectile.py- Cannonball trajectories, basketball shots, angle comparisons02_collision_detection.py- Car crashes, near misses, asteroid collisions03_force_energy_momentum.py- F=ma, kinetic energy, momentum conservation04_r3f_visualization.py- Generate React Three Fiber visualization data
# Run any example
python examples/00_quick_start.py
python examples/01_simple_projectile.py
# ... etcRequires Rapier Service
These examples demonstrate rigid-body simulations and Phase 1 features. They need the Rapier service running:
05_rapier_simulation.py- Bouncing balls, collisions, stacking boxes06_bounce_detection.py- Phase 1.1: Automatic bounce detection and energy analysis07_contact_events.py- Phase 1.2: Real-time contact tracking and collision events08_pendulum.py- Phase 1.3: Joints and constraints (pendulums, chains)09_phase1_complete.py- Phase 1.4: All Phase 1 features (damping, bounces, contacts, joints)10_fluid_dynamics.py- Phase 1.5: Fluid calculations (drag, buoyancy, terminal velocity)11_rotational_dynamics.py- Phase 2.1: Torque, angular momentum, gyroscopes12_oscillations.py- Phase 2.2: Springs, pendulums, harmonic motion, damping13_circular_motion.py- Phase 2.3: Orbital mechanics, centripetal force14_statics.py- Phase 2.6: Static equilibrium, force balance, beam analysis15_kinematics_analysis.py- Phase 2.7: Motion analysis, trajectory fitting16_roulette_simulation.py- 🎰 Casino Roulette - Complete showcase of multi-body physics, collisions, and energy dissipation
# Option 1: Use public Rapier service (easiest)
export RAPIER_SERVICE_URL=https://rapier.chukai.io
python examples/05_rapier_simulation.py
python examples/06_bounce_detection.py
# ... etc
# Option 2: Run local Rapier service with Docker
docker run -p 9000:9000 chuk-rapier-service
export RAPIER_SERVICE_URL=http://localhost:9000
python examples/05_rapier_simulation.pyNote:
Examples 00-04 work instantly (no external services)
Examples 05-09 showcase advanced rigid-body physics with Rapier
Use the public Rapier service at
https://rapier.chukai.ioor run your own
⚙️ Configuration
Environment Variables
# Provider selection
PHYSICS_PROVIDER=analytic # or "rapier"
# Rapier service (only if using Rapier provider)
# The default is automatically determined:
# - On Fly.io: uses https://rapier.chukai.io (public service)
# - Locally: uses http://localhost:9000
#
# Override with:
RAPIER_SERVICE_URL=https://rapier.chukai.io # or http://localhost:9000
# Optional configuration
RAPIER_TIMEOUT=30.0
RAPIER_MAX_RETRIES=3
RAPIER_RETRY_DELAY=1.0YAML Configuration
Create physics.yaml in your working directory or ~/.config/chuk-mcp-physics/:
default_provider: rapier
providers:
# Override provider per tool type
simulations: rapier
projectile_motion: analytic
rapier:
# Public service (recommended)
service_url: https://rapier.chukai.io
# Or local development
# service_url: http://localhost:9000
timeout: 30.0
max_retries: 3
retry_delay: 1.0🛡️ Safety & Limits
Recommended Ranges
Understanding these limits helps prevent timeouts, instabilities, and confusion:
Parameter | Recommended | Maximum | Notes |
Units | meters, kg, seconds | - | SI units throughout |
dt | 0.008 - 0.033 | 0.001 - 0.1 | <0.008 = overkill, >0.033 = unstable |
steps | 100 - 5000 | 10,000 | Depends on dt and complexity |
bodies | 1 - 100 | 1,000 | Performance degrades >100 |
gravity | -20 to 0 m/s² | -100 to +100 | Earth = -9.81 |
velocity | 0 - 100 m/s | 1,000 m/s | Very high speeds may cause tunneling |
mass | 0.1 - 10,000 kg | 1e-6 - 1e6 | Extreme ratios cause instability |
Public Service Limits
The public Rapier service at https://rapier.chukai.io has these limits:
Max steps per call: 5,000
Max bodies per simulation: 100
Max concurrent simulations: 10 per IP
Request timeout: 30 seconds
Max simulation lifetime: 1 hour (auto-cleanup)
For larger simulations, run your own Rapier service (see RAPIER_SERVICE.md).
Common Pitfalls
❌ Simulation explodes or bodies fly away
Symptoms:
Bodies gain extreme velocities
Objects disappear from view
NaN values in positions
Causes:
dttoo large for the forces involvedVery high mass ratios (1g object hitting 1000kg object)
Extreme initial velocities
Solutions:
Reduce
dtto 0.008 or lowerUse more similar masses (within 2-3 orders of magnitude)
Limit initial velocities to <100 m/s
❌ Simulation runs very slowly
Symptoms:
Request takes >10 seconds
Timeout errors
High CPU usage
Causes:
Too many bodies (>100)
Very small
dt(<0.005)Complex mesh colliders
Too many steps (>5000)
Solutions:
Reduce body count or simplify shapes
Increase
dt(balance accuracy vs. speed)Break large step counts into multiple calls
Use primitive shapes (sphere, box) instead of meshes
❌ Objects tunnel through each other
Symptoms:
Fast-moving objects pass through walls
Collisions not detected
Objects appear inside each other
Causes:
Very high velocities + large
dtThin colliders (<0.1m)
Disabled continuous collision detection (CCD)
Solutions:
Reduce
dtfor high-speed scenariosThicken colliders (minimum 0.1m recommended)
Reduce velocities
Enable CCD if available (future feature)
Best Practices
Start simple: Test with 2-3 bodies before scaling up
Validate inputs: Check for NaN, Inf, extreme values before simulation
Monitor performance: Track step time, adjust
dt/steps accordinglyCleanup: Always
destroy_simulationwhen done (prevent memory leaks)Use analytic when possible: For simple scenarios, analytic is faster and exact
🔧 Development
# Navigate to project directory
cd chuk-mcp-physics
# Install in development mode
make dev-install
# Run tests
make test
# Run tests with coverage
make test-cov
# Format code
make format
# Run all checks
make check
# Build package
make build🐳 Docker Deployment
# Build image
make docker-build
# Run container
make docker-run
# Access at http://localhost:8000☁️ Production Deployment
Live Public Services
Current Production Services:
MCP Physics Server: https://physics.chukai.io/mcp
Public hosted MCP server endpoint
No local installation required
Pre-configured with Rapier service
Ready to use in Claude Desktop
Rapier Physics Engine: https://rapier.chukai.io
Public API for physics simulations
No authentication required for basic usage
Rate limits may apply
Quick Test:
# Test the public Rapier service
curl https://rapier.chukai.io/health
# Use with chuk-mcp-physics locally
export RAPIER_SERVICE_URL=https://rapier.chukai.io
uvx chuk-mcp-physicsDeploy Your Own Rapier Service
If you need your own private Rapier service instance:
1. Deploy Rapier Service to Fly.io with Redis
cd rapier-service
# Login to Fly.io
fly auth login
# Create Redis instance for distributed storage
fly redis create
# Choose: your-rapier-redis, region sjc (or your preferred region), plan 256MB
# Set Redis URL secret (use URL from previous step)
fly secrets set REDIS_URL="redis://default:password@fly-your-rapier-redis.upstash.io"
# Create and deploy the service
fly apps create your-rapier-physics
fly deploy
# Verify Redis connection in logs
fly logs
# Look for: "📦 Initialized RedisStorage backend"
# Add custom domain (optional)
fly certs add rapier.yourdomain.com -a your-rapier-physics
# Verify service is running
curl https://your-rapier-physics.fly.dev/healthRedis Benefits:
✅ Horizontal scaling (multiple service instances share state)
✅ Automatic cleanup (TTL-based simulation expiration)
✅ Distributed coordination across instances
✅ Session persistence within TTL window
Configuration:
The service uses Redis automatically on Fly.io (see rapier-service/fly.toml). For local development, it defaults to in-memory storage.
See rapier-service/FLY_REDIS_SETUP.md for detailed Redis setup guide, monitoring, and troubleshooting.
2. Configure chuk-mcp-physics to Use Your Service
# Option 1: Environment variable
export RAPIER_SERVICE_URL=https://rapier.yourdomain.com
uvx chuk-mcp-physics
# Option 2: YAML config (physics.yaml)
# rapier:
# service_url: https://rapier.yourdomain.comWhy deploy your own?
🔒 Private instance for production workloads
📈 Custom scaling and resource allocation
🌍 Deploy closer to your users (different regions)
💾 Persistent simulations and custom configurations
See DEPLOYMENT.md for complete deployment guide, scaling strategies, and CI/CD setup.
🦀 Rapier Service Setup
For full rigid-body simulations, you have several options:
Option 1: Use Public Service (Easiest)
# No setup required - just configure the URL
export RAPIER_SERVICE_URL=https://rapier.chukai.io
uvx chuk-mcp-physicsOption 2: Run Locally with Docker
# Using Docker
docker run -p 9000:9000 chuk-rapier-service
# Configure to use local service
export RAPIER_SERVICE_URL=http://localhost:9000
uvx chuk-mcp-physicsOption 3: Build from Source
# Build and run the Rust service
cd rapier-service
cargo run --release
# In another terminal
export RAPIER_SERVICE_URL=http://localhost:9000
uvx chuk-mcp-physicsSee RAPIER_SERVICE.md for:
Complete API specification
Rust implementation guide
Docker deployment details
Testing examples
📊 Comparison: Analytic vs Rapier
Feature | Analytic Provider | Rapier Provider |
Projectile motion | ✅ Exact (kinematic eqs) | ✅ Simulated |
Simple collisions | ✅ Exact (sphere-sphere, elastic) | ✅ Simulated |
Force/energy/momentum | ✅ F=ma, KE, PE, momentum, work/power | ✅ Can derive from sim |
Fluid dynamics | ✅ Drag, buoyancy, terminal velocity | ❌ Not supported |
Rigid-body dynamics | ❌ Not supported | ✅ Full 3D/2D physics |
Complex shapes | ❌ Spheres only | ✅ Box, capsule, mesh, etc |
Friction/restitution | ❌ Not modeled | ✅ Full material properties |
Multi-body systems | ❌ Not supported | ✅ Unlimited bodies |
Constraints/joints | ❌ Not supported | ✅ Hinges, sliders, etc |
Performance | ⚡ Instant | 🐇 Fast (Rust) |
Setup | 📦 Built-in | 🦀 Requires Rapier service |
Recommendation:
Use Analytic for simple calculations, education, quick answers
Use Rapier for complex simulations, games, visualizations, multi-body dynamics
🤝 Contributing
Contributions welcome! Please see CONTRIBUTING.md.
📄 License
Apache License 2.0 - see LICENSE for details.
This is a demonstration project provided as-is for learning and testing purposes.
🙏 Acknowledgments
Rapier - Fast 2D/3D physics engine in Rust
Model Context Protocol - Protocol specification
📚 See Also
RAPIER_SERVICE.md - Rapier microservice specification
Examples - Example usage patterns
API Documentation - Detailed tool reference
Available Tools
62 toolsadd_jointA
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
),
)
Inputs: sim_id (required), joint (required).
add_rigid_bodyA
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]
)
Inputs: sim_id (required), body_id (required), body_type (required), shape (required), +17 more.
analyze_circular_orbitA
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
Inputs: altitude (required), planet_mass (required), planet_radius (required), gravitational_constant.
calculate_acceleration_from_positionA
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]]
)
Inputs: times (required), positions (required).
calculate_angular_accelerationA
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²
Inputs: torque (required), moment_of_inertia (required).
calculate_angular_momentumA
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)
Inputs: moment_of_inertia (required), angular_velocity_x (required), angular_velocity_y (required), angular_velocity_z (required).
calculate_average_speedA
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]
)
Inputs: positions (required), times (required).
calculate_banking_angleA
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°
Inputs: velocity (required), radius (required), gravity.
calculate_beam_reactionsA
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]
)
Inputs: beam_length (required), loads (required), load_positions (required).
calculate_bernoulliA
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
)
Inputs: pressure1 (required), velocity1 (required), height1 (required), velocity2, +3 more.
calculate_buoyancyA
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
Inputs: volume (required), fluid_density (required), gravity, submerged_fraction.
calculate_center_of_massA
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]
Inputs: masses (required), positions (required).
calculate_centripetal_forceA
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)
Inputs: mass (required), velocity (required), radius (required).
calculate_damped_oscillationA
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
Inputs: mass (required), spring_constant (required), damping_coefficient (required), time (required), +2 more.
calculate_drag_forceA
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
)
Inputs: velocity (required), cross_sectional_area (required), fluid_density (required), drag_coefficient, +1 more.
calculate_elastic_collisionA
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
Inputs: mass1 (required), velocity1 (required), mass2 (required), velocity2 (required).
calculate_elastic_collision_3dA
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
Inputs: mass1 (required), velocity1 (required), mass2 (required), velocity2 (required).
calculate_escape_velocityA
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
Inputs: mass (required), radius (required), gravitational_constant.
calculate_forceA
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")
Inputs: mass (required), acceleration_x (required), acceleration_y (required), acceleration_z (required).
calculate_hookes_lawA
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
Inputs: spring_constant (required), displacement (required).
calculate_inelastic_collision_3dA
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
Inputs: mass1 (required), velocity1 (required), mass2 (required), velocity2 (required), +1 more.
calculate_instantaneous_velocityA
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
Inputs: positions (required), times (required), target_time (required).
calculate_jerkA
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)
Inputs: times (required), accelerations (required).
calculate_kinetic_energyA
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")
Inputs: mass (required), velocity_x (required), velocity_y (required), velocity_z (required).
calculate_lift_forceA
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
)
Inputs: velocity (required), wing_area (required), lift_coefficient (required), fluid_density.
calculate_magnus_forceA
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
)
Inputs: velocity (required), angular_velocity (required), radius (required), fluid_density.
calculate_moment_of_inertiaA
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²
Inputs: shape (required), mass (required), radius, length, +4 more.
calculate_momentumA
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")
Inputs: mass (required), velocity_x (required), velocity_y (required), velocity_z (required).
calculate_normal_forceA
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
Inputs: mass (required), gravity, angle_degrees, additional_force.
calculate_orbital_periodA
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
Inputs: orbital_radius (required), central_mass (required), gravitational_constant.
calculate_pendulum_periodA
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
Inputs: length (required), gravity, amplitude_degrees.
calculate_potential_energyA
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
Inputs: mass (required), height (required), gravity.
calculate_pressure_at_depthA
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
Inputs: depth (required), fluid_density (required), atmospheric_pressure, gravity.
calculate_projectile_motionA
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")
Inputs: initial_velocity (required), angle_degrees (required), initial_height, gravity.
calculate_projectile_with_dragA
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!
Inputs: initial_velocity (required), angle_degrees (required), mass (required), cross_sectional_area (required), +11 more.
calculate_reynolds_numberA
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
Inputs: velocity (required), characteristic_length (required), fluid_density (required), dynamic_viscosity (required).
calculate_rotational_kinetic_energyA
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
Inputs: moment_of_inertia (required), angular_velocity (required).
calculate_simple_harmonic_motionA
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
)
Inputs: amplitude (required), angular_frequency (required), time (required), phase.
calculate_spring_mass_periodA
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
Inputs: mass (required), spring_constant (required).
calculate_static_frictionA
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)
Inputs: normal_force (required), coefficient_static_friction (required), applied_force.
calculate_terminal_velocityA
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)
Inputs: mass (required), cross_sectional_area (required), fluid_density (required), drag_coefficient, +1 more.
calculate_torqueA
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
Inputs: force_x (required), force_y (required), force_z (required), position_x (required), +2 more.
calculate_venturi_effectA
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)
Inputs: inlet_diameter (required), throat_diameter (required), inlet_velocity (required), fluid_density (required).
calculate_work_powerA
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
Inputs: force (required), displacement (required), time.
check_angular_momentum_conservationA
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
)
Inputs: initial_angular_momentum (required), final_angular_momentum (required), tolerance.
check_collisionA
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")
Inputs: body1_position (required), body1_velocity (required), body1_radius (required), body2_position (required), +3 more.
check_energy_conservationA
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
)
Inputs: initial_kinetic_energy (required), final_kinetic_energy (required), initial_potential_energy (required), final_potential_energy (required), +2 more.
check_equilibriumA
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]]
)
Inputs: forces (required), force_positions (required), pivot_point, tolerance.
check_force_balanceA
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
Inputs: forces (required), tolerance.
check_momentum_conservationA
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
)
Inputs: initial_momentum (required), final_momentum (required), tolerance.
check_torque_balanceA
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
)
Inputs: torques (required), tolerance.
convert_unitA
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"
}
Inputs: value (required), from_unit (required), to_unit (required).
create_simulationA
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.
Inputs: gravity_x, gravity_y, gravity_z, dimensions, +2 more.
destroy_simulationA
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)
Inputs: sim_id (required).
fit_trajectoryA
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²
Inputs: times (required), positions (required), fit_type.
generate_motion_graphA
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
Inputs: times (required), positions (required), component.
list_unit_conversionsA
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"],
...
}
Inputs: no named parameters.
record_trajectoryA
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
Inputs: sim_id (required), body_id (required), steps (required), dt.
record_trajectory_with_eventsA
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")
Inputs: sim_id (required), body_id (required), steps (required), dt, +2 more.
simulate_underwater_motionA
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
)
Inputs: initial_velocity (required), mass (required), volume (required), cross_sectional_area (required), +7 more.
step_simulationA
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}")
Inputs: sim_id (required), steps, dt.
track_energy_dissipationA
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
Inputs: trajectory_data (required), mass (required), gravity, reference_height.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 62 tools
Many tools have overlapping purposes, such as calculate_elastic_collision vs calculate_elastic_collision_3d, which are essentially the same operation in 1D vs 3D. Similarly, check_force_balance and check_equilibrium both verify force balance, and check_equilibrium also includes torque balance, causing potential confusion. The distinction between some tools (e.g., calculate_orbital_period vs analyze_circular_orbit) is subtle and may lead to misselection.
Most tools follow a consistent 'calculate_' or 'check_' or 'simulate_' prefix pattern, making them predictable. However, there are minor inconsistencies like 'list_unit_conversions' (no verb prefix) and 'convert_unit' without a consistent prefix, plus some names like 'track_energy_dissipation' vs 'calculate_energy' are not parallel. Overall, the pattern is readable but not perfectly uniform.
With 62 tools, this server is extremely heavy. Many tools are highly specialized (e.g., calculate_bernoulli, calculate_venturi_effect) and could be combined or consolidated. The sheer number overwhelms an agent and makes selection difficult. Some tools are redundant variations (1D vs 3D collisions) that inflate the count without adding distinct value.
The tool surface covers a comprehensive range of mechanics (kinematics, dynamics, fluids, oscillations, rotational motion, statics) and includes simulation capabilities with CRUD-like operations (create, add, step, record, destroy). Missing pieces include wave mechanics, electromagnetism, quantum physics, or thermal physics, which are beyond the server's apparent scope. Within its mechanical focus, coverage is solid, though there is no explicit 'get_simulation_state' tool separate from step_simulation, and no batch operations for large parameter sweeps.
Maintenance
Related MCP Connectors
AI-callable calculators and engineering models with real formulas. No hallucinated math.
Physics calculators that show their work, plus the CODATA 2022 constants. Educational use.
Deterministic reasoning stack for AI agents: simulate, decide & compute, plus cross-domain tools.
Aircraft intelligence for AI agents: valuations with uncertainty bands, FAA registry lookups, cost of ownership, comparable aircraft, fleet search, airworthiness directives and STCs, market metrics and forecasts, verified value reports, pre-buy diligence checklists, logbook search and a watchlist. 38 tools; free tier with OAuth or a Windsock API key.
Related MCP Servers
- AlicenseNot gradedqualityDmaintenanceEnables physicists to perform computer algebra calculations, create scientific plots, solve differential equations, work with tensor algebra and quantum mechanics, and parse natural language physics problems. Supports unit conversion, physical constants, and generates comprehensive reports with optional GPU acceleration.11MIT
- AlicenseNot gradedqualityBmaintenanceVerified unit conversion and dimensional analysis for AI agents. 190+ units, 31 domain formulas (clinical, physics, aerospace, SRE), physical constants with uncertainty propagation. Refuses invalid conversions structurally: the tool that won't convert mg to mL and knows the difference between torque and energy.AGPL 3.0
- AlicenseNot gradedqualityDmaintenanceExposes MuJoCo physics simulation to AI assistants via 65 MCP tools, enabling natural language control of robotics simulation, trajectory optimization, contact analysis, and video export.10MIT
- AlicenseBqualityCmaintenanceEnables LLMs to run arbitrary-precision integer and bitwise operations, endianness swaps, IEEE 754 float decomposition, hashing/checksum/modular math, data codecs, statistics, and trigonometry through 29 specialized tools. Its chained batch execution engine lets multiple dependent steps run in one call, eliminating multi-turn round-trip overhead.2923 npm19MIT