Research & implementation report
LeRobot MCP 0.2.0 migration
Updated LeRobot contracts and migrated to official MCP SDK 2.2.0. Real v0.6.1 dataset/CLI checks, modern and legacy stdio, concurrency checks, source audits of main, and isolated wheel startup passed.
Contract
- User outcome
- Current LeRobot dataset, policy processor, and CLI contracts; MCP SDK 2.x; release on main.
- Acceptance target
- Preserve existing tools and scalar arguments, accept nested JSON, inspect a real v3 dataset, expose current processor artifacts, pass MCP protocol and package checks.
- Compatibility
- Tool names and result payloads retained with additive fields. Metadata targets LeRobot >=0.6.1. MCP 2026-07-28 and legacy 2025-11-25 clients tested.
- Safety
- No hardware motion, dataset upload, or model execution during validation. Conversion remains opt-in and local by default.
- Experiment mandate
- Adaptive correctness checks; no performance target.
- Non-goals
- Training policies, calibrating physical robots, HTTP transport, and migrating existing user datasets.
Research
| Source | Finding | Implementation impact | Link |
|---|---|---|---|
| LeRobot v0.6.1 release | Latest stable GitHub release inspected on 2026-09-25; commit 7e241bd630a3719a56157a497ce5d08f244784f1. | Use as the real-runtime validation target. | Open |
| LeRobot package and extras | Feature-scoped dataset/training/core_scripts/evaluation extras and dynamically declared console scripts. | Keep source discovery; document extras instead of hardcoding all commands or installing every policy. | Open |
| Dataset metadata and typed info | Metadata exposes DatasetInfo attributes, authoritative totals, depth keys, and dataset/bucket repo types. Format remains v3.0. | Replace obsolete dict access, add total frames and modality keys, and expose bucket selection. | Open |
| Policy processor serialization | Pipeline configs contain steps with optional state_file references. Factory defaults are policy_preprocessor.json and policy_postprocessor.json. | Inspect pipelines, separate processor state from policy weights, and report missing artifacts. | Open |
| Dataset converter | Converter still uses argparse flags for v2.1-to-v3.0; branch is an upload destination. | Retain conversion implementation and verify flags against source; correct parameter documentation. | Open |
| Current main source | Current source includes new policies, inference and rollout registries, and additional commands. | AST registration discovery and CI contract checks track source evolution without importing robotics modules. | Open |
| Official MCP SDK migration guide | SDK 2 uses MCPServer, snake_case types, worker threads, explicit ToolError messages, and a modern Client discovery flow. | Migrate imports, annotations, clients and errors; protect shared mutable state; test both protocol eras. | Open |
Architecture decision
Keep one dynamic CLI/inspection interface. Concentrate serialization and subprocess behavior in the runner, static source contracts in introspection, and checkpoint declarations in Hub inspection.
Interface
Existing MCP tools plus nested JSON options, scoped help, version metadata, dataset bucket selection, and additive policy processor/action fields.
Seams and adapters
- LeRobot checkout and subprocess runtime remain separate from the MCP Python environment.
- Hub listing and lightweight JSON reads use one commit snapshot; processor configurations never overwrite policy features.
- Official MCPServer handles protocol framing; one registration adapter preserves expected errors and local locks protect configuration and jobs.
Alternatives
| Alternative | Decision |
|---|---|
| Per-command hardcoded wrappers | Rejected: duplicate evolving LeRobot configuration contracts and lag newly registered commands. |
| Import all LeRobot registries into MCP | Rejected: introduces heavy dependencies and optional hardware/model imports at discovery time. |
| Standalone FastMCP framework | Rejected: official SDK MCPServer covers the existing tool surface without a second framework. |
Baseline
| Metric | Baseline | Context |
|---|---|---|
| Existing suite | 21 passed | Original repository tests; no real upstream metadata or SDK 2 checks. |
Experiments
| ID | Family | Hypothesis | Change | Result | Evidence signal | Decision | Raw evidence |
|---|---|---|---|---|---|---|---|
| E01 | LeRobot runtime | Current typed metadata can replace obsolete dict access without changing existing outputs. | Use DatasetInfo attributes and public totals; add bucket/modality fields; create/finalize/read a three-frame dataset. | improved | Real v0.6.1 metadata and CLI help passed. | promote | Open |
| E02 | Contract discovery | Source parsing and processor-aware inspection cover modern configs without importing models. | AST registries, nested JSON serialization, upstream draccus parse, commit-pinned processor inspection and feature precedence. | improved | Nested split mapping parsed by real LeRobot; source contracts pass stable and main; policy regressions pass. | promote | Open |
| E03 | Dependency compatibility | A dependency-only SDK upgrade might preserve the old server imports. | Resolved MCP 2.2.0 before migrating server imports. | failed | Collection failed: mcp.server.fastmcp was removed. | retire | Open |
| E04 | MCP protocol migration | Official SDK 2 migration can preserve existing tools and support concurrent callers. | MCPServer, Client, annotations, version, expected errors and state locks. Initial wire tests exposed sanitized ValueError messages; ToolError adapter fixed them. | improved | Modern/legacy stdio, foreground responsiveness, concurrent setup/cancel, all 35 tests and isolated wheel startup passed. | promote | Open |
Validation
Limitations and blockers
- No physical robots, model inference, remote storage buckets, or dataset conversion writes were exercised.
- Policy inspection reports declared schemas and artifact presence; it does not prove joint order, units, or safe runtime compatibility.
- Current main was validated statically; real runtime validation used v0.6.1 on macOS arm64.
- Managed installation continues to follow main by default; select ref=v0.6.1 for the stable validation baseline.
- Browser URL policy blocked opening the local HTML report. HTML headings, tables, evidence links, and overflow CSS were checked statically; visual layout was not reviewed.
Reproduction
- uv sync --extra dev --frozen
- uv run ruff check . && uv run mypy
- uv run pytest -q
- In a LeRobot v0.6.1 checkout: uv sync --locked --no-default-groups --extra dataset --python 3.12
- LEROBOT_CONTRACT_ROOT=/path/to/lerobot LEROBOT_CONTRACT_RUNTIME=1 uv run pytest -q
- With a main checkout: LEROBOT_CONTRACT_ROOT=/path/to/main uv run pytest tests/test_upstream_contract.py -q
- uv build; install the resulting wheel into a clean environment and run a Client(StdioServerParameters(command="lerobot-mcp")) discovery/config smoke check.