This release supports fastsim-plugin-server[kinematics]>=0.8.3,<0.9 and
fastsim[kinematics]>=0.1.0a19,<0.2 when the optional Server integration is installed.
The gateway uses only the Server's public HTTP contract. It does not import
FastSim internals, inspect private application state, or bypass the Server's
authority and lifecycle checks.
MCP host ── stdio ──> fastsim-mcp ── bounded HTTP ──> fastsim-server ──> FastSimApplication
no simulator ownership owns one Run slot
The package is inert when it is not started. Starting fastsim-mcp creates an
HTTP client but performs no request until an MCP tool is called. It never starts
the HTTP Server or opens a simulator on its own. If neither the Server nor this
gateway is running, FastSim has no MCP callbacks, polling, serialization, network,
or per-tick overhead.
Start in three steps
Run the installer once from the FastSim Plugins repository root:
./packages/fastsim-plugin-mcp/install.sh
It installs the gateway into an isolated lightweight Python environment, creates
the fastsim-mcp command, and registers it automatically when Codex CLI is
available. It uses a standalone system Python when possible or asks Conda to create
a dedicated prefix; it never reuses the Isaac Lab environment. For another MCP host,
print generic configuration JSON instead:
./packages/fastsim-plugin-mcp/install.sh --client json
Start FastSim normally on subsequent runs:
fastsim-server run.yaml
Check the connection only when needed:
fastsim-mcp doctor
Restart the Agent and ask it in natural language to build or revise a standalone scene configuration, inspect the scene, read robot state, capture a camera, pause, or control the current Run. Users do not supply a Server URL, generation, idempotency key, reason, or MCP JSON in the default local workflow. The Agent reads and creates the required protocol metadata itself.
For diagnosis, simply ask the Agent to investigate the current Run. The
fastsim_debug_bundle tool collects the bounded Run, scene, control, plugin,
operation, log, metric, optional geometry, and optional camera evidence concurrently,
so the Agent does not need a slow serial chain of low-level calls.
If the package is already installed, registration alone is:
fastsim-mcp setup
The MCP process and FastSim Server use separate Python environments. Only the HTTP Server process needs FastSim, Isaac Lab, or another simulator backend.
Advanced connection setup
The default Server is http://127.0.0.1:8000. Re-run setup for another origin:
fastsim-mcp setup --url https://fastsim.example.com --force
Only Agent-selected configuration launch or planning geometry reads require the corresponding advanced Server options:
fastsim-server \
--launch-root examples=/absolute/path/to/configs \
--planning-reads \
--authority operator
Loopback HTTP needs no bearer token under the Server's default policy. For a
token-protected Server, inject FASTSIM_HTTP_TOKEN through the MCP host's secret
or process environment. Do not commit a token in client configuration. There is
deliberately no command-line token option, so a token is not exposed in process
arguments.
The gateway supports stdio transport only. It does not open a listening socket.
<details> <summary>Advanced protocol and complete tool reference</summary>
Low-level connection settings
| CLI option | Environment | Default and bounds |
|---|---|---|
--url ORIGIN |
FASTSIM_HTTP_URL |
http://127.0.0.1:8000; exact http/https origin only |
--timeout SECONDS |
FASTSIM_MCP_TIMEOUT |
15; finite 0.1..120 |
--max-json-bytes N |
FASTSIM_MCP_MAX_JSON_BYTES |
4194304; 1 KiB..16 MiB |
--max-image-bytes N |
FASTSIM_MCP_MAX_IMAGE_BYTES |
16777216; 1 KiB..64 MiB |
--audit-log ABSOLUTE_PATH |
FASTSIM_MCP_AUDIT_LOG |
stderr; parent directory must already exist |
| none | FASTSIM_HTTP_TOKEN |
unset; bounded bearer token sent only to the configured origin |
The origin is fixed by the operator. Tools cannot supply or replace it. URLs with credentials, a path prefix, query, fragment, unsupported scheme, or invalid port are rejected. Redirect following and proxy-environment inheritance are disabled. JSON and PNG bodies are size-limited while streaming into memory.
Tool catalog
All inputs are strict JSON objects. Unknown fields and coercion are rejected.
Every input schema declares JSON Schema draft 2020-12 and
additionalProperties: false; nested track and frame schemas are strict as
well. tools/list is the canonical, machine-readable schema source generated
directly from the validation models.
Read-only tools
| Tool | Inputs | Public FastSim result |
|---|---|---|
fastsim_health |
target: live, ready, or both (default) |
Process liveness and/or admission readiness |
fastsim_capabilities |
none | Authority-aware fastsim-http/1 capability declaration |
fastsim_run_status |
none | Current Run metadata and persistent launch-slot generation |
fastsim_run_snapshot |
none | Bounded public FastSimApplication snapshot |
fastsim_debug_bundle |
optional entity IDs, camera ID, geometry switch, and bounded page limits | Concurrent Agent-ready Run, scene, control, plugin, operation, log, metric, geometry, and camera evidence with per-section errors |
fastsim_scenario |
section: summary (default), source, scene, behavior, or evaluation |
Immutable Scenario projection |
fastsim_plugin_status |
optional instance |
Bounded plugin-host snapshot or one public plugin instance |
fastsim_plugin_events |
after_sequence 0..2^63-1 (default 0), limit 1..100 (default 50), optional instance, topic |
Ordered, bounded public plugin events |
fastsim_server_logs |
after_sequence 0..2^63-1, limit 1..500, wait_s 0..30 |
Bounded, redacted Server and plugin events |
fastsim_process_metrics |
none | One demand-driven server-process CPU, memory, and optional GPU sample |
fastsim_run_artifacts |
exact slot generation |
Bounded descriptors for committed Run artifacts; never artifact bytes |
fastsim_list_entities |
unique entity_ids, link_ids, and kinds lists (at most 32 each), optional enabled, offset 0..100000, limit 1..200 |
Page of public entities, links, and articulations |
fastsim_inspect_entity |
exact entity_id |
Joined static scene catalog and committed dynamic state |
fastsim_robot_state |
exact entity_id |
Articulation descriptor and ordered joint state |
fastsim_camera_screenshot |
entity_id matching sensors.*; optional finite timeout_s in (0,30] |
Bounded PNG plus Run, generation, tick, and simulation-time metadata |
fastsim_deformable_state |
entity_id matching deformables.*, sample_count 0..64, optional timeout |
Whole-body bounds, centroid, speed statistics, and evenly distributed node samples |
fastsim_frame_transform |
source, target, optional generation 1..2^63-1 |
One explicit planning-frame transform |
fastsim_geometry_references |
bounded entity/motion/layer/purpose/representation filters, include_transforms, offset 0..100000, limit 1..200 |
Path-free geometry descriptors and optional committed transforms |
fastsim_solve_ik |
robot, base/tip frames, target pose; optional group, tolerances, timeout, collision mode, seed, and solution count | Selected Provider's bounded IK result and joint solutions; never executes control |
fastsim_control_targets |
none | Controllable actors, resource groups, axes, command spaces, and controllers |
fastsim_control_status |
optional finite timeout_s in (0,30] |
Public control context |
fastsim_list_operations |
offset 0..100000, limit 1..100, optional exact state and kind |
Bounded asynchronous-operation page |
fastsim_operation_status |
lowercase UUID operation_id |
One exact lifecycle/control operation |
Entity-like identifiers are 1..256 characters and contain only letters,
digits, _, ., :, /, or -, beginning with an alphanumeric character.
Short identifiers are at most 128 characters. Filter lists reject duplicates.
fastsim_geometry_references accepts motion classes dynamic, kinematic, and
static; purposes collision, planning_proxy, and visual; and these
representations: box, capsule, compound, convex_mesh, cylinder,
heightfield, halfspace, sdf, sphere, triangle_mesh, and voxel.
It returns public resource references, never geometry bytes or host paths.
Mutating tools
Every mutation requires confirm: true and a trimmed reason of 1..256
characters. A false, missing, mistyped, or surplus value is rejected before any
HTTP request. Asynchronous lifecycle, launch, and control submissions require an
idempotency_key of 1..128 safe characters and accept wait_timeout_s from
0..60. Direct scene commands instead make command_id and generation
optional: Core binds/generates omitted values, while an advanced caller can
provide a stable command_id when retrying the exact same command.
| Tool | Additional inputs and limits | Fences and preflight |
|---|---|---|
fastsim_run_lifecycle |
action: prepare, start, pause, resume, step, reset, stop, or close; expected_generation; count 1..1000 only for step |
Checks the named lifecycle capability; sends idempotency and slot-generation headers |
fastsim_launch_catalog_run |
launch-root alias; safe relative .yaml, .yml, .json, or .toml config; target_state: open, prepared, or running |
Checks configuration-write capability and that the alias is published by /api/v1/launch; arbitrary host paths are impossible |
fastsim_launch_config |
complete standalone YAML, JSON, or TOML text up to 1 MiB; portable filename; target_state: open, prepared, or running |
Checks configuration-write and upload capabilities plus the Server-advertised byte limit; the normal FastSim compiler remains authoritative |
fastsim_set_entity_pose |
existing entity_id; world xyz_m; identity-default quat_xyzw; optional generation, command_id, and deadline |
Checks the public pose capability; MCP handles replaceable Server-slot fencing automatically |
fastsim_attach_entity |
rigid or articulated child; rigid/articulated parent; optional parent/child link and relative pose | Creates one fixed physical relationship and returns its attachment_id |
fastsim_detach_entity |
rigid or articulated child and returned attachment_id |
Removes that relationship without resetting the child articulation |
fastsim_begin_entity_drag |
existing entity_id; world grab_point_world_m; optional generation, command_id, drag_id, and deadline |
Returns the Core drag_id; checks the public drag capability and handles any Server-slot fence |
fastsim_update_entity_drag |
existing entity_id; returned drag_id; world pose; optional generation, command identity, and deadline |
Forwards one update to the same Core drag transaction |
fastsim_end_entity_drag |
existing entity_id; returned drag_id; optional generation, command identity, and deadline |
Ends the Core drag transaction |
fastsim_cancel_entity_drag |
existing entity_id; returned drag_id; optional generation, command identity, and deadline |
Cancels the Core drag transaction |
fastsim_submit_joint_path |
actor/group; 1..256 equal-width frames; 1..64 axes; at most 16,384 finite values within +/-1e9; finite dt in (0,10]; optional timeout (0,300]; preempt; expected_generation |
Checks control-write capability and exact public actor/group target; sends idempotency and slot-generation headers |
fastsim_submit_tracks |
1..16 non-overlapping tracks and at most 2,048 frames total; optional timeout (0,300]; preempt; expected_generation |
Checks control-write capability and every exact public entity/resource target; sends idempotency and slot-generation headers |
fastsim_cancel_operation |
lowercase UUID operation_id |
Reads current status first and refuses terminal operations; Server decides cancellability |
Each physical track contains:
entity_id,resource_group, and versionedcontrollerandcommand_spaceidentifiers such asjoint.passthrough@1;1..512frames beginning at0.0seconds with strictly increasing times;1..64unique axes, equally sized finite values and unit lists, stable across the track, with an optional stable frame identifier;interpolationequal tozero_order_hold(default) orlinear; and- optional JSON
semantics, bounded to depth 8, 1,024 entries, 128-character keys, and 2,048 UTF-8 bytes per string.
The FastSim HTTP Server remains authoritative. MCP-side validation and preflight
reduce ambiguous or stale requests but do not replace Server-side schema,
authority, lifecycle, generation, resource, or controller validation.
Scene tools only move existing entities. They do not spawn assets or reimplement
drag physics. IK is a separate read-only compute tool and never moves the robot.
Scene-command results directly include status, run_id,
generation, scene_sequence, sim_tick, and any attachment_id, drag_id, or rejection details.
Result contract
Every tool returns structured content and a JSON text block using one envelope:
{
"ok": true,
"tool": "fastsim_run_status",
"api_version": "fastsim-http/1",
"data": {}
}
Mutations also include bounded public audit metadata. Camera screenshots add one
MCP image/png content block. Failures set MCP isError and use a sanitized
error envelope:
{
"ok": false,
"tool": "fastsim_run_status",
"api_version": "fastsim-http/1",
"error": {
"code": "application_not_ready",
"message": "application is not ready",
"retryable": true,
"http_status": 503,
"request_id": "request-id-if-published"
}
}
Bearer tokens, request bodies, local paths, stack traces, and exception reprs are
not placed in tool errors. The gateway fails closed on a protocol version other
than fastsim-http/1.
Mutation audit
Before any network mutation, the gateway appends a requested JSON Lines record.
It appends accepted after the Server accepts the request or rejected after a
known failure. If the pre-mutation record cannot be persisted, the mutation is
not sent.
{"schema":"fastsim-mcp-audit/1","timestamp":"2026-08-26T12:00:00+00:00","audit_id":"...","tool":"fastsim_run_lifecycle","target":"run:step","reason":"advance one reviewed tick","outcome":"requested","idempotency_key_sha256":"...","expected_generation":7}
Raw idempotency keys and bearer tokens are never recorded. The default destination
is stderr, which is separate from the MCP stdio protocol stream. For durable logs,
set an absolute audit path in an existing operator-owned directory; files are
created with mode 0600. Protect, rotate, and retain that file according to the
deployment's policy.
An accepted audit result means the HTTP submission was accepted, not that an
asynchronous operation ultimately succeeded. Inspect the returned state or call
fastsim_operation_status.
Recommended operating sequence
- Call
fastsim_healthandfastsim_capabilities. - Call
fastsim_run_status; record the current slot generation. - If the slot is idle, use
fastsim_launch_catalog_runfor an operator-managed configuration, orfastsim_launch_configfor complete Agent-authored text after reviewing its scene poses, reason, and idempotency key. - Refresh
fastsim_run_statusafter launch or replacement. - Before control, call
fastsim_control_targetsand the relevant state/geometry reads. Submit with that exact generation. - Inspect the returned operation or use a bounded
wait_timeout_s; cancel only by explicit operation UUID.
Never reuse an idempotency key for a different request. A stale generation is a safety signal: refresh state and re-evaluate the command rather than silently retrying it against a replacement Run.
Deliberate limitations
This release does not expose:
- arbitrary HTTP requests, caller-selected origins, Server startup/shutdown, or MCP-over-HTTP transport;
- multi-file configuration uploads, arbitrary host paths, Run artifact bytes, or
local resource locators;
fastsim_launch_configaccepts one standalone config only; - scene/entity mutation, direct plugin method invocation, or plugin installation;
- depth, normals, segmentation, contacts, particle-fluid state, geometry bytes, or subscriptions; or
- autonomous retries, unbounded polling, background workers, simulator callbacks, or per-tick hooks.
These omissions are capability boundaries, not undocumented tools. Extend the
public FastSim/Server contract first when a new operation is needed.
In particular, a Server without writes.entity_mutation publishes it as false; this
gateway therefore does not invent scene-spawn or scene-delete tools.
Development and verification
cd packages/fastsim-plugin-mcp
python -m pip install -e '.[test]'
ruff check .
mypy src tests
pytest -q
python -m build
The protocol suite verifies exact paths, headers, bodies, MCP schemas, capability denial, audit ordering, response limits, authentication, camera content, and no-I/O construction. It also exercises every published tool through the current compatible Server ASGI application and the MCP stdio transport. The deterministic reference application is not a GPU simulator, so those checks do not claim GPU, GUI, or live simulator-backend coverage.
</details>