sionna-mcp
by Alexli18
README.md
# sionna-mcp
MCP server exposing NVIDIA Sionna RT ray-tracing as 15 structured tools for AI agents.
## Install
```bash
pip install -e ".[dev]"
```
**Requirements**: Python 3.11+, `sionna>=1.0` (tested with 1.2.2), `mcp[cli]>=1.0`, PyTorch with CUDA (optional but recommended).
> **Jetson / no-OptiX note**: On NVIDIA Jetson (aarch64) and other systems without OptiX, sionna-mcp automatically falls back to the LLVM CPU backend (`llvm_ad_mono_polarized`). CUDA-accelerated ray tracing requires OptiX (`libnvoptix.so.1`), available only on x86_64.
## Run
```bash
# Direct
python server.py
# As installed CLI (after pip install -e .)
sionna-mcp
```
The server uses `stdio` transport (MCP standard). Configure your agent runtime to spawn it as a subprocess.
## Built-in Scenes
Pass `"builtin:<name>"` as `scene_path` in `load_scene` to use Sionna's bundled scenes without copying files:
| Name | Description |
|------|-------------|
| `builtin:etoile` | Paris Étoile roundabout (urban macro) |
| `builtin:munich` | Munich city block |
| `builtin:florence` | Florence street scene |
| `builtin:san_francisco` | San Francisco urban |
| `builtin:simple_street_canyon` | Simple two-building canyon |
| `builtin:simple_reflector` | Single flat reflector |
For custom scenes, place the `.xml` file in `SIONNA_SCENES_ROOT` and use the filename as `scene_path`.
## Environment Variables
| Variable | Default | Description |
|----------|---------|-------------|
| `SIONNA_SCENES_ROOT` | `./scenes` | Root dir for scene XML files |
| `SIONNA_ARTIFACTS_ROOT` | `./artifacts` | Root dir for output artifacts |
| `SIONNA_MAX_DEPTH` | `8` | Max ray tracing depth (0–8) |
| `SIONNA_MAX_SUBCARRIERS` | `4096` | Max subcarrier count |
| `SIONNA_MAX_TRAJECTORY` | `1000` | Max trajectory length |
| `SIONNA_MCP_DEBUG` | `0` | Set to `1` for traceback in error responses |
## Tools (16)
### Environment
- **`sionna_status`** — Check Sionna/PyTorch/CUDA availability
### Scene Management
- **`load_scene`** — Load scene XML at a carrier frequency
- **`inspect_scene`** — List objects, nodes, and array configs in a loaded scene
### Node Management
- **`add_transmitter`** — Place a TX node (position, orientation, power_dbm)
- **`add_receiver`** — Place an RX node
- **`add_drone_receiver`** — Place a drone RX with velocity + antenna offset
- **`update_node_pose`** — Update TX/RX position and orientation
### Antenna Arrays
- **`set_antenna_array`** — Configure planar array (pattern, polarization, rows×cols) for TX or RX
### Ray Tracing
- **`compute_paths`** — Run Sionna PathSolver; returns `job_id`
- **`extract_cir_tool`** — Extract CIR `(a, tau)` as NPZ artifact
- **`extract_cfr_tool`** — Extract CFR as NPY artifact
- **`extract_csi_tool`** — Extract CSI with shape `[N_tx, N_rx, N_sub, N_ant]` as complex64
### Dataset Generation
- **`run_trajectory`** — Loop drone over positions, extract channel per position, save labeled samples; supports micro-Doppler via `propeller_rpm`/`num_blades`/`propeller_ids`
- **`export_dataset`** — Bundle all trajectory samples into a single NPZ file
- **`get_artifact`** — Retrieve local path + size for a `sionna://` URI
### Sim-to-Real
- **`inject_noise`** — Add AWGN and/or phase jitter to a CSI `.npy` artifact; accepts single file or dataset directory
## Error Codes
| Code | Meaning |
|------|---------|
| `SCENE_NOT_LOADED` | `scene_id` not in registry |
| `JOB_NOT_FOUND` | `job_id` not in registry |
| `PATH_TRAVERSAL_DENIED` | Scene path escapes `SIONNA_SCENES_ROOT` |
| `DUPLICATE_TX_ID` | Transmitter ID already used in scene |
| `DUPLICATE_RX_ID` | Receiver/node ID already used in scene |
| `NODE_NOT_FOUND` | Node ID not found in scene |
| `DRONE_NOT_FOUND` | Drone not registered via `add_drone_receiver` |
| `TX_NOT_FOUND` / `RX_NOT_FOUND` | Unknown IDs in `compute_paths` |
| `RUNTIME_LIMIT_EXCEEDED` | PathSolver exceeded `max_runtime_seconds` |
| `DEPTH_LIMIT_EXCEEDED` | `max_depth > SIONNA_MAX_DEPTH` |
| `TRAJECTORY_LIMIT_EXCEEDED` | Trajectory exceeds `SIONNA_MAX_TRAJECTORY` points |
| `UNSUPPORTED_PATTERN` | Antenna pattern not supported |
| `INVALID_URI` | Malformed `sionna://` URI or path traversal |
| `ARTIFACT_NOT_FOUND` | Artifact file not on disk |
| `INVALID_NOISE_PARAMS` | `snr_db` out of range or `phase_jitter_deg < 0` |
| `SIONNA_NOT_AVAILABLE` | Sionna/torch import failed |
| `SIONNA_INTERNAL_ERROR` | Sionna raised an unexpected exception |
| `INVALID_POSITION` | NaN/Inf in position or orientation vector |
## Using with an AI Agent
sionna-mcp uses the [MCP (Model Context Protocol)](https://modelcontextprotocol.io) stdio transport.
Any MCP-compatible agent (Claude Code, Claude Desktop, Cursor, etc.) can drive it.
### Claude Code
Add to your project's `.claude/mcp.json`:
```json
{
"mcpServers": {
"sionna-mcp": {
"command": "python",
"args": ["/absolute/path/to/sionna-mcp/server.py"],
"env": {
"SIONNA_SCENES_ROOT": "/absolute/path/to/scenes",
"SIONNA_ARTIFACTS_ROOT": "/absolute/path/to/artifacts"
}
}
}
}
```
Or if installed as a CLI (`pip install -e .`):
```json
{
"mcpServers": {
"sionna-mcp": {
"command": "sionna-mcp",
"env": {
"SIONNA_SCENES_ROOT": "/absolute/path/to/scenes",
"SIONNA_ARTIFACTS_ROOT": "/absolute/path/to/artifacts"
}
}
}
}
```
Then start Claude Code in your project — the agent will have all 15 tools available automatically.
### Claude Desktop
Add to `~/Library/Application Support/Claude/claude_desktop_config.json` (macOS) or
`%APPDATA%\Claude\claude_desktop_config.json` (Windows):
```json
{
"mcpServers": {
"sionna-mcp": {
"command": "python",
"args": ["/absolute/path/to/sionna-mcp/server.py"]
}
}
}
```
Restart Claude Desktop after saving.
### What to tell the agent
Once connected, you can give the agent natural-language tasks. Examples:
> "Load the Munich scene at 3.5 GHz, place a base station TX at [0, 0, 30] and a UE receiver at [50, 0, 1.5], run ray tracing with 3 reflections, and extract CSI with 64 subcarriers."
> "Simulate a drone flying 10 positions along the X-axis from [0,0,50] to [90,0,50], collecting channel data at each point and exporting a labeled NPZ dataset."
> "Check if Sionna and CUDA are available on this machine."
The agent will call the tools in the correct order, handle `job_id` / `artifact_uri` chaining between steps, and return the final file path to you.
### Typical tool call sequence
```
sionna_status → confirm environment
load_scene → returns scene_id
set_antenna_array → configure TX/RX arrays (optional)
add_transmitter → returns tx_id
add_receiver / add_drone_receiver → returns rx_id / drone_id
compute_paths → returns job_id (PathSolver runs here)
extract_csi_tool → returns artifact_uri (sionna://...)
get_artifact → returns local file path + size
```
For drone datasets:
```
load_scene → add_transmitter → add_drone_receiver
→ run_trajectory (loops internally over all positions)
→ export_dataset → get_artifact
```
### Example sessions
- `examples/urban_single_tx_rx.json` — single-link urban simulation (3.5 GHz, 2×2 MIMO)
- `examples/drone_trajectory.json` — 10-position drone CSI dataset (5.8 GHz)
## CSI Shape Convention
CSI has canonical shape `[N_tx, N_rx, N_sub, N_ant]` in complex64:
- `N_tx` — number of transmitters
- `N_rx` — number of receivers
- `N_sub` — number of subcarriers (equals `num_subcarriers` parameter)
- `N_ant` — virtual MIMO antenna product: `N_tx_ant × N_rx_ant`
## Reproducibility (SC-003)
Set `seed` in `compute_paths` and ensure `diffraction=False` for reproducible CSI across runs.
- **CUDA backend** (x86_64 with OptiX): byte-identical results across runs with the same seed.
- **LLVM backend** (Jetson / no OptiX): numerically reproducible, max per-element difference < 1e-6.
## Running Tests
```bash
pytest tests/unit/ # No Sionna required
pytest tests/integration/ # Requires Sionna installed
```
## Tool Contracts
See `specs/001-home-jetson-sionna/contracts/tools.md` for full JSON schema contracts.
This server cannot be deployed
Maintenance
ActivityMaintained
ResponsivenessSyncing