Skip to main content
Glama
ros-claw

rosclaw-ur-rtde-mcp

by ros-claw
README.md
# rosclaw-ur-rtde-mcp

🌐 **English** | [δΈ­ζ–‡](./README.zh.md)

ROSClaw MCP Server for Universal Robots β€” using **ur_rtde** (RTDE protocol, direct TCP, no ROS2 required). **With Robotiq Gripper support** (port 63352 via UR Cap).

Part of the [ROSClaw](https://github.com/ros-claw) Embodied Intelligence Operating System.

## SDK Information

| Property | Value |
|----------|-------|
| **SDK Name** | ur_rtde |
| **SDK Version** | 1.0.0+ |
| **Protocol** | RTDE (Real-Time Data Exchange) |
| **Source Repository** | [gitlab.com/sdurobotics/ur_rtde](https://gitlab.com/sdurobotics/ur_rtde) |
| **Documentation** | [ur_rtde Docs](https://sdurobotics.gitlab.io/ur_rtde/) |
| **License** | MIT |
| **Generated** | 2026-04-07 |

## Hardware Specification

| Specification | Value |
|--------------|-------|
| **Supported Robots** | UR3, UR5, UR10, UR16, UR20 |
| **Controller Types** | CB3 Series, e-Series |
| **Protocol** | RTDE over TCP |
| **Robot Port** | 30004 (RTDE) |
| **Dashboard Port** | 29999 |
| **Gripper Port** | 63352 (Robotiq via UR Cap) |
| **Max Joint Speed** | 3.14 rad/s |
| **Max Tool Speed** | 3.0 m/s |
| **Max Joint Acceleration** | 40 rad/sΒ² |

### PolyScope Compatibility

| PolyScope Version | Compatibility | Notes |
|-------------------|---------------|-------|
| 5.6.0+ | βœ… Full | All features supported |
| 3.x - 5.5.x | βœ… Compatible | Some dashboard features return "N/A" |
| CB3 Series | βœ… Compatible | Tested on PolyScope 3.15.8 |
| e-Series | βœ… Compatible | Recommended for best performance |

## Features

| Category | Tools |
|----------|-------|
| Connection | `connect_robot`, `disconnect_robot` |
| Robot Lifecycle | `get_robot_info`, `robot_power_control`, `unlock_protective_stop`, `restart_safety` |
| Motion | `move_joint`, `move_linear`, **`move_joint_ik`** (NEW), `stop_motion`, `servo_joint`, `speed_joint` |
| Force Control | `force_mode`, `force_mode_stop`, `zero_ft_sensor` |
| Teaching | `teach_mode`, `jog` |
| Kinematics | `get_inverse_kinematics` |
| Payload | `set_payload` |
| I/O | `set_digital_output`, `set_speed_slider`, `set_analog_output`, `get_digital_io_state` |
| State | `get_robot_state`, `get_tcp_pose`, `get_joint_positions`, `get_tcp_force` |
| **Robotiq Gripper** | `connect_gripper`, `disconnect_gripper`, `gripper_activate`, `gripper_open`, `gripper_close`, `gripper_move`, `gripper_get_status` |
| **SDK Info** | `get_sdk_info` |

**MCP Resources**: `robot://status`, `robot://connection`, `robot://sdk_info`

## Quick Start

```bash
# Install dependencies
pip install ur-rtde mcp

# Run MCP server
python src/ur_rtde_mcp_server.py

# Or with uv
uv venv --python 3.11
source .venv/bin/activate
uv pip install ur-rtde mcp
python src/ur_rtde_mcp_server.py
```

## Claude Desktop Configuration

Add to `claude_desktop_config.json`:

```json
{
  "mcpServers": {
    "rosclaw-ur-rtde": {
      "command": "python",
      "args": ["/path/to/rosclaw-ur-rtde-mcp/src/ur_rtde_mcp_server.py"],
      "transportType": "stdio",
      "description": "UR via RTDE with Gripper Support",
      "sdk_version": "1.0.0+",
      "sdk_source": "https://gitlab.com/sdurobotics/ur_rtde"
    }
  }
}
```

## LLM Usage Example β€” Robot Arm

```
User: Connect to the robot at 192.168.1.100, move to home position, then check TCP force.

LLM calls:
1. connect_robot("192.168.1.100")
2. robot_power_control("brake_release")   # if needed
3. move_joint([0, -1.57, 0, -1.57, 0, 0])  # home position
4. get_tcp_force()
```

## LLM Usage Example β€” Robotiq Gripper

```
User: Connect to the robot and gripper, then pick up an object.

LLM calls:
1. connect_robot("192.168.1.100")
2. connect_gripper()                     # Connects to same IP, port 63352
3. gripper_activate()                    # Activates + auto-calibrates
4. gripper_open()                        # Open before picking
5. move_joint([...])                     # Move above object
6. gripper_close(speed=128, force=100)   # Close with controlled force
7. move_joint([...])                     # Move to drop position
8. gripper_open()                        # Release object
```

### moveJ_IK β€” Cartesian Pose Control (NEW)

The `move_joint_ik` tool moves the robot to a Cartesian pose using inverse kinematics (faster than moveL, more intuitive than joint angles).

```python
# Move to specific Cartesian pose [x, y, z, rx, ry, rz]
move_joint_ik(
    pose=[-0.212, 0.319, 0.41, -3.1416, 0, 0],  # meters + rotation vector
    speed=0.5,                                    # rad/s (conservative)
    acceleration=0.8                              # rad/sΒ²
)
```

**Use Case**: When you know the desired TCP position in Cartesian space but don't want to calculate joint angles manually.

## Safety Information

**WARNING:** This MCP server controls an industrial robot arm. Improper use can cause:
- Serious injury or death
- Equipment damage
- Property damage

### Safety Features

| Feature | Description |
|---------|-------------|
| **Joint Velocity** | Max 3.14 rad/s enforced |
| **Tool Velocity** | Max 3.0 m/s enforced |
| **Joint Acceleration** | Max 40 rad/sΒ² enforced |
| **Protective Stop Check** | `check_safe_to_move()` blocks commands during stop |
| **Emergency Stop** | Physical E-stop on pendant |

### Safety Levels

| Level | Color | Description | Example |
|-------|-------|-------------|---------|
| **CRITICAL** | πŸ”΄ | Immediate danger | Collision, protective stop |
| **HIGH** | 🟠 | Potential damage | Near joint limits |
| **MEDIUM** | 🟑 | Caution needed | Force mode active |
| **LOW** | 🟒 | Informational | Status check |

### Emergency Procedures

1. **Immediate Stop**: Press physical E-stop or call `stop_motion()`
2. **Protective Stop**: Wait 5s, then call `unlock_protective_stop()`
3. **Power Off**: Use `robot_power_control("power_off")` if needed

## Error Handling

### Error Codes

| Code | Name | Severity | Description |
|------|------|----------|-------------|
| -1 | CONNECTION_FAILED | 🟠 error | RTDE connection failed |
| -2 | TIMEOUT | 🟠 error | Command response timeout |
| -3 | INVALID_PARAMETER | 🟠 error | Invalid joint angle or pose |
| -4 | SAFETY_VIOLATION | πŸ”΄ critical | Exceeds velocity/acceleration limits |
| -5 | PROTECTIVE_STOP | πŸ”΄ critical | Robot in protective stop |
| -6 | NOT_INITIALIZED | 🟠 error | Not connected to robot |

### Troubleshooting

| Issue | Possible Cause | Solution |
|-------|---------------|----------|
| Connection failed | Wrong IP | Verify robot IP address |
| Connection failed | Network issue | Check Ethernet cable |
| Command rejected | Protective stop | Unlock protective stop |
| Command rejected | Not in remote | Enable remote control mode |
| Gripper not responding | UR Cap not installed | Install Robotiq_grippers cap |
| Slow motion | Speed slider | Check speed slider setting |

## Hardware Requirements

- **Universal Robots**: UR3, UR5, UR10, UR16, UR20 (CB3 or e-Series)
- **Communication**: RTDE over TCP port 30004
- **Optional - Robotiq Gripper**: TCP port 63352 (via Robotiq_grippers UR Cap)
- **Optional - F/T Sensor**: Required for `force_mode` and `zero_ft_sensor`

### Gripper Position

| Position | Value | Description |
|----------|-------|-------------|
| 0 | Fully open | Fingers at maximum spread |
| 255 | Fully closed | Fingers fully closed |
| 128 | Halfway | 50% closure |

Use `gripper_move(position=64, speed=255, force=100)` for precise positioning.

## Architecture

```
LLM (Claude)
    β”‚ MCP tools (semantic level)
    β–Ό
ur_rtde_mcp_server.py   (FastMCP, stdio)
    β”‚
ur_rtde_bridge.py       (thread-safe wrapper, threading.Lock)
    β”œβ”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”€β”
    β”‚                                       β”‚
ur_rtde Python bindings              robotiq_gripper.py
    β”‚ TCP port 30004                       β”‚ TCP port 63352
    β–Ό                                       β–Ό
UR Robot Controller (RTDE)         Robotiq Gripper (UR Cap)
```

## File Structure

```
rosclaw-ur-rtde-mcp/
β”œβ”€β”€ src/
β”‚   β”œβ”€β”€ ur_rtde_mcp_server.py   # MCP server with FastMCP (~600 lines)
β”‚   β”œβ”€β”€ ur_rtde_bridge.py       # Thread-safe bridge for RTDE/IO/Dashboard (~270 lines)
β”‚   └── robotiq_gripper.py      # Robotiq gripper direct TCP control (297 lines)
β”œβ”€β”€ tests/
β”‚   β”œβ”€β”€ test_ur_rtde_bridge.py  # Unit tests for bridge (15 passed)
β”‚   β”œβ”€β”€ test_robotiq_gripper.py # Unit tests for gripper (15 passed)
β”‚   β”œβ”€β”€ system_test_moveJ_IK.py # System test for moveJ_IK feature (hardware required)
β”‚   β”œβ”€β”€ full_function_test.py   # Complete system test for all MCP tools (hardware required)
β”‚   β”œβ”€β”€ diagnose_failures.py    # Diagnostic tool for troubleshooting
β”‚   └── failure_analysis_report.md # Analysis of test failures
β”œβ”€β”€ config/
β”‚   └── mcp_config.json         # MCP client configuration
β”œβ”€β”€ pyproject.toml
β”œβ”€β”€ README.md
└── LICENSE
```

## Testing

### Unit Tests (No Hardware Required)

```bash
# Run all unit tests (30 total, no hardware required)
pytest tests/test_ur_rtde_bridge.py tests/test_robotiq_gripper.py -v

# Run specific test file
pytest tests/test_ur_rtde_bridge.py -v
pytest tests/test_robotiq_gripper.py -v
```

### System Tests (Hardware Required)

⚠️ **Warning**: These tests require a real UR robot. Ensure safety before running.

```bash
# Test moveJ_IK feature (requires robot at ROBOT_IP in the script)
python tests/system_test_moveJ_IK.py

# Full functional test of all MCP tools
python tests/full_function_test.py

# Diagnostic tool for troubleshooting
python tests/diagnose_failures.py
```

### Test Reports

System tests generate timestamped reports:
- `ur5_system_test_report_YYYYMMDD_HHMMSS.txt`
- `ur5_full_test_report_YYYYMMDD_HHMMSS.txt`

## References

- [ur_rtde GitLab](https://gitlab.com/sdurobotics/ur_rtde)
- [ur_rtde Documentation](https://sdurobotics.gitlab.io/ur_rtde/)
- [Universal Robots RTDE Guide](https://www.universal-robots.com/articles/ur/interface-communication/real-time-data-exchange-rtde-guide/)
- [Robotiq Gripper Manual](https://robotiq.com/support/2f-85-2f-140)
- [MCP Protocol](https://modelcontextprotocol.io/)

## Changelog

### v0.2.0 (2025-03-25)
- ✨ **NEW**: Added `moveJ_IK` method to `URRTDEBridge` for Cartesian pose control via IK
- ✨ **NEW**: Added comprehensive system tests for hardware validation
- ✨ **NEW**: Added diagnostic tools for troubleshooting
- ✨ **NEW**: Added SDK metadata and `get_sdk_info()` tool
- πŸ› **FIX**: `get_robot_info` now handles PolyScope < 5.6.0 gracefully
- πŸ“š **DOC**: Updated README with compatibility matrix and new features

### v0.1.0 (Initial Release)
- Initial MCP server implementation
- Support for UR robots via RTDE protocol
- Robotiq gripper support
- Thread-safe bridge implementation

## License

MIT License β€” See [LICENSE](LICENSE)

The underlying ur_rtde library is also MIT licensed.

## Part of ROSClaw

- [rosclaw](https://github.com/ros-claw/rosclaw) β€” Core framework (see [arXiv paper](https://arxiv.org/pdf/2604.04664))
- [rosclaw-g1-dds-mcp](https://github.com/ros-claw/rosclaw-g1-dds-mcp) β€” Unitree G1 humanoid
- [rosclaw-ur-ros2-mcp](https://github.com/ros-claw/rosclaw-ur-ros2-mcp) β€” UR5 via ROS2/MoveIt
- [rosclaw-gimbal-mcp](https://github.com/ros-claw/rosclaw-gimbal-mcp) β€” GCU gimbal
- [rosclaw-ur-rtde-mcp](https://github.com/ros-claw/rosclaw-ur-rtde-mcp) β€” UR via RTDE (this repo)

---

**Generated by ROSClaw SDK-to-MCP Transformer**

*SDK Version: ur_rtde 1.0.0+ | Protocol: RTDE (TCP) | With Robotiq Gripper Support*