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.

text
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:

bash
./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:

bash
./packages/fastsim-plugin-mcp/install.sh --client json

Start FastSim normally on subsequent runs:

bash
fastsim-server run.yaml

Check the connection only when needed:

bash
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:

bash
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:

bash
fastsim-mcp setup --url https://fastsim.example.com --force

Only Agent-selected configuration launch or planning geometry reads require the corresponding advanced Server options:

bash
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 versioned controller and command_space identifiers such as joint.passthrough@1;
  • 1..512 frames beginning at 0.0 seconds with strictly increasing times;
  • 1..64 unique axes, equally sized finite values and unit lists, stable across the track, with an optional stable frame identifier;
  • interpolation equal to zero_order_hold (default) or linear; 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:

json
{
  "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:

json
{
  "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.

json
{"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.

  1. Call fastsim_health and fastsim_capabilities.
  2. Call fastsim_run_status; record the current slot generation.
  3. If the slot is idle, use fastsim_launch_catalog_run for an operator-managed configuration, or fastsim_launch_config for complete Agent-authored text after reviewing its scene poses, reason, and idempotency key.
  4. Refresh fastsim_run_status after launch or replacement.
  5. Before control, call fastsim_control_targets and the relevant state/geometry reads. Submit with that exact generation.
  6. 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_config accepts 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

bash
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>