Gym MCP Client
A unified Python interface for working with both local and remote Gymnasium environments via gym-mcp-server.
Goal: Write code once, seamlessly switch between local development and remote execution.
Features
- 🎮 Unified API: Same Gymnasium interface for both local and remote environments
- 🔄 Seamless Switching: Change modes with a single parameter
- 🌐 Remote Execution: Connect to gym-mcp-server instances over HTTP
- 🔧 Full Compatibility: Supports all Gymnasium environment types (Box, Discrete, MultiBinary, etc.)
- 🐍 Modern Python: Python 3.12+ with complete type hints
- 📦 Easy Setup: Managed with uv for fast dependency management
- ✅ Well Tested: 14 comprehensive tests, all passing
Installation
# Clone the repository
git clone <your-repo-url>
cd gym-mcp-client
# Install with uv (recommended)
uv sync
# Or with pip
pip install -e .
Quick Start
Local Mode
from gym_mcp_client import GymMCPClient
# Create a local environment
env = GymMCPClient("CartPole-v1", mode="local")
# Use standard Gymnasium API
observation, info = env.reset(seed=42)
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action)
env.close()
Remote Mode
First, start a gym-mcp-server:
python -m gym_mcp_server --env CartPole-v1 --transport streamable-http --port 8000
Then connect to it:
from gym_mcp_client import GymMCPClient
# Create a remote environment
env = GymMCPClient(
"CartPole-v1",
mode="remote",
gym_server_url="http://localhost:8000"
)
# Use the exact same API as local mode!
observation, info = env.reset(seed=42)
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action)
env.close()
Context Manager
from gym_mcp_client import GymMCPClient
# Automatic cleanup
with GymMCPClient("CartPole-v1", mode="local") as env:
observation, info = env.reset()
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action)
# env.close() called automatically
Switching Between Modes
The main benefit: write once, run anywhere!
import os
from gym_mcp_client import GymMCPClient
# Configuration from environment variables
MODE = os.getenv("GYM_MODE", "local")
SERVER_URL = os.getenv("GYM_SERVER_URL", "http://localhost:8000")
# Create environment based on mode
if MODE == "local":
env = GymMCPClient("CartPole-v1", mode="local")
else:
env = GymMCPClient(
"CartPole-v1",
mode="remote",
gym_server_url=SERVER_URL,
gym_server_key=os.getenv("GYM_API_KEY")
)
# Your code works the same regardless of mode!
observation, info = env.reset()
for _ in range(1000):
action = env.action_space.sample()
observation, reward, terminated, truncated, info = env.step(action)
if terminated or truncated:
observation, info = env.reset()
env.close()
Switch modes via command line:
# Run locally
export GYM_MODE=local
python your_training_script.py
# Run remotely
export GYM_MODE=remote
export GYM_SERVER_URL=http://gpu-server:8000
python your_training_script.py
API Reference
GymMCPClient
GymMCPClient(
env_id: str,
mode: str = "local",
render_mode: str | None = None,
gym_server_url: str | None = None,
gym_server_key: str | None = None,
**kwargs
)
Parameters:
env_id: Gymnasium environment ID (e.g., "CartPole-v1")mode: Either "local" or "remote"render_mode: Render mode ("rgb_array", "human", etc.)gym_server_url: URL of gym-mcp-server (required for remote mode)gym_server_key: Optional API key for authentication**kwargs: Additional arguments passed togym.make()in local mode
Methods:
reset(seed=None, options=None)→ (observation, info)step(action)→ (observation, reward, terminated, truncated, info)render()→ render_outputclose()→ None
Properties:
observation_space: The observation spaceaction_space: The action spacereward_range: The reward rangemetadata: Environment metadata
Architecture
┌─────────────────┐
│ Your Code │
└────────┬────────┘
│
▼
┌─────────────────┐
│ GymMCPClient │
└────────┬────────┘
│
┌────┴────┐
▼ ▼
┌────────┐ ┌──────────────┐
│ Local │ │ Remote │
│ Gym │ │ HTTP Client │
└────────┘ └──────┬───────┘
│
▼
┌──────────────┐
│ gym-mcp- │
│ server │
└──────┬───────┘
│
▼
┌────────┐
│ Gym │
│ Env │
└────────┘
Supported Space Types
| Space Type | Local | Remote | Serialization |
|---|---|---|---|
| Box | ✅ | ✅ | array ↔ list |
| Discrete | ✅ | ✅ | int ↔ int |
| MultiBinary | ✅ | ✅ | array ↔ list |
| MultiDiscrete | ✅ | ✅ | array ↔ list |
| Tuple | ✅ | ✅ | recursive |
| Dict | ✅ | ✅ | recursive |
Examples
See the examples/ directory:
local_example.py: Local mode usageremote_example.py: Remote mode usagecontext_manager_example.py: Context manager pattern
Run examples:
# Local mode
uv run python examples/local_example.py
# Remote mode (start server first!)
python -m gym_mcp_server --env CartPole-v1 --transport streamable-http --port 8000
uv run python examples/remote_example.py
# Demo CLI tool
python main.py --mode local --episodes 3
Development
Setup
git clone <your-repo-url>
cd gym-mcp-client
make install
Available Commands
make help # Show all commands
make test # Run test suite (14 tests)
make lint # Run ruff linter
make format # Format code with ruff
make typecheck # Run mypy type checker
make check # Run all checks (lint + typecheck + test)
make all # Format, then run all checks
make demo # Run local demo
make clean # Clean build artifacts
Running Tests
make test
# Or: uv run pytest tests/ -v
# 14 tests, all passing ✅
Use Cases
- Development → Production: Develop locally, deploy remotely
- Distributed Training: Multiple processes connecting to remote environments
- Resource Management: Run expensive simulations on dedicated servers
- Testing: Test locally before remote deployment
Performance
Local Mode
- Overhead: Minimal (thin wrapper)
- Best for: Development, testing, lightweight environments
Remote Mode
- Overhead: HTTP round-trip (1-10ms on localhost)
- Best for: Expensive environments, distributed training, resource sharing
Error Handling
from gym_mcp_client import GymMCPClient
import httpx
try:
env = GymMCPClient(
"CartPole-v1",
mode="remote",
gym_server_url="http://localhost:8000"
)
observation, info = env.reset()
# ... your code ...
except ValueError:
# Invalid mode, missing URL, etc.
pass
except RuntimeError:
# Environment initialization failed, remote call failed
pass
except httpx.HTTPError:
# Network error (remote mode only)
pass
finally:
if 'env' in locals():
env.close()
Troubleshooting
Remote Connection Issues
- Ensure the gym-mcp-server is running and accessible
- Check URL is correct (including protocol:
http://orhttps://) - Verify firewall/network settings
- Check server logs for errors
Environment Not Found
# For Atari environments
uv add "gymnasium[atari]"
# For Box2D environments
uv add "gymnasium[box2d]"
# For MuJoCo environments
uv add "gymnasium[mujoco]"
Requirements
- Python 3.12+
- gymnasium >= 1.2.1
- httpx >= 0.28.1
- numpy >= 2.0.0
- gym-mcp-server (from GitHub)
Contributing
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Run
make checkto verify all tests pass - Submit a Pull Request
See CONTRIBUTING.md for detailed guidelines.
License
MIT License - see LICENSE file for details.
Related Projects
- gym-mcp-server - MCP server for Gymnasium environments
- Gymnasium - RL environment standard
- Model Context Protocol - Tool integration protocol
Support
- Issues: Open a GitHub issue
- Questions: Start a GitHub discussion
- Documentation: See examples/ directory
Status: ✅ Production Ready | Version: 0.1.0 | Python: 3.12+
Metadata
Release files for gym-mcp-client 0.1.0
For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.
Source distribution (sdist)
| File | Size | Uploaded | |
|---|---|---|---|
| gym_mcp_client-0.1.0.tar.gz | 12.1 kB | Details |
Built distribution (wheel)
| File | Interpreter | ABI | Platform | Reset |
|---|---|---|---|---|
| gym_mcp_client-0.1.0-py3-none-any.whl | Python 3 | none | any | Details |
Total release size: 21.7 kB
Release files / gym_mcp_client-0.1.0.tar.gz
| Download URL | gym_mcp_client-0.1.0.tar.gz |
|---|---|
| Size | 12.1 kB |
| Tags | Source |
|
SHA-256 checksum How to use checksums |
f432bafcd227da9f627f66d8e8cc6bd14f8fe3b8df451e600f52cb0d3791f17c
|
|
BLAKE2b-256 checksum How to use checksums |
a82e3b366894d7a082f36f31828c0992ae2a5087b25cb20f8d4afe6aff5bb76c
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|
Release files / gym_mcp_client-0.1.0-py3-none-any.whl
| Download URL | gym_mcp_client-0.1.0-py3-none-any.whl |
|---|---|
| Size | 9.6 kB |
| Tags | Python 3 |
|
SHA-256 checksum How to use checksums |
2c1fb0e89af4aa05b74f1c6e800db1084459e54aadc9dbff13bf69d0e361453b
|
|
BLAKE2b-256 checksum How to use checksums |
45ae0fdecda9f88359cd8ecd60c71549116e30a063102a04fc50d7b3460a3995
|
| Upload date | |
|
Uploaded using Trusted Publishing? What is trusted publishing? |
No |
| Uploaded via |
twine/6.2.0 CPython/3.13.5
|