{"_id":"@ai-rpg-engine/sidecar","_rev":"6-5a5cce19b4d38c9cf90e761e66b0a916","name":"@ai-rpg-engine/sidecar","dist-tags":{"latest":"3.12.0"},"versions":{"0.0.0":{"name":"@ai-rpg-engine/sidecar","version":"0.0.0","author":{"name":"mcp-tool-shop","email":"64996768+mcp-tool-shop@users.noreply.github.com"},"license":"MIT","_id":"@ai-rpg-engine/sidecar@0.0.0","maintainers":[{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"}],"homepage":"https://mcp-tool-shop-org.github.io/ai-rpg-engine/","bugs":{"url":"https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"},"dist":{"shasum":"6cd0f391e42185ab74802844e22c05ff3eb18cc5","tarball":"https://registry.npmjs.org/@ai-rpg-engine/sidecar/-/sidecar-0.0.0.tgz","fileCount":2,"integrity":"sha512-pPlgsALcu4QWhL5xS4R48PEuB7LJFalhXlR2V0rKh7x4lRZJu3MWB8wOykPHYghppTMIdOxiBSZRj7WxAGVWLQ==","signatures":[{"sig":"MEUCIAISoC+6Q6dJIXNtJRh+OKRolOu1VGSPENLrWCM/cpuEAiEAqH8VIMrIa0RhDWYtyTylIKPXxOcdmStf2+Vb2mvjQVc=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"unpackedSize":716},"_npmUser":{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"},"repository":{"url":"git+https://github.com/mcp-tool-shop-org/ai-rpg-engine.git","type":"git"},"_npmVersion":"10.9.8","description":"Placeholder — real release v3.8.1+ coming soon. See https://github.com/mcp-tool-shop-org/ai-rpg-engine","directories":{},"_nodeVersion":"22.22.3","_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sidecar_0.0.0_1788156414514_0.30067674963738344","host":"s3://npm-registry-packages-npm-production"}},"3.8.1":{"name":"@ai-rpg-engine/sidecar","version":"3.8.1","keywords":["rpg","json-rpc","sidecar","game-engine","protocol","deterministic"],"author":{"name":"mcp-tool-shop"},"license":"MIT","_id":"@ai-rpg-engine/sidecar@3.8.1","maintainers":[{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"}],"homepage":"https://mcp-tool-shop-org.github.io/ai-rpg-engine/","bugs":{"url":"https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"},"dist":{"shasum":"0a0cac645d06b7680563be67774192fc04198d0a","tarball":"https://registry.npmjs.org/@ai-rpg-engine/sidecar/-/sidecar-3.8.1.tgz","fileCount":38,"integrity":"sha512-i3Z5mWDDoCZqAD6MixioaMkS81lhudzFB9Zb20P7lC4cD5MRL0EU2HENib0bbB9u0RhUgT31B0Ldjc2wU/wikQ==","signatures":[{"sig":"MEUCIDWGxunVz1VlF7e35fUZmcmerQ9h52Toef33wZaNyH/JAiEA/kZq+lckb8wZ8k1i4JVxQmCuqnWhcf9GUsMLvP5mJNY=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-rpg-engine%2fsidecar@3.8.1","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":232887},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"49c63c5d7df474979c1b775c40988ac46714eb03","scripts":{"test":"vitest run","build":"tsc"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ce01d16a-e466-44c8-b23a-0ebd8fca88e1"}},"repository":{"url":"git+https://github.com/mcp-tool-shop-org/ai-rpg-engine.git","type":"git","directory":"packages/sidecar"},"_npmVersion":"11.19.1","description":"JSON-RPC sidecar for the AI RPG Engine — one authoritative sim process, N rendering clients","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@ai-rpg-engine/core":"*"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sidecar_3.8.1_1788156897482_0.09021470623134142","host":"s3://npm-registry-packages-npm-production"}},"3.9.0":{"name":"@ai-rpg-engine/sidecar","version":"3.9.0","keywords":["rpg","json-rpc","sidecar","game-engine","protocol","deterministic"],"author":{"name":"mcp-tool-shop"},"license":"MIT","_id":"@ai-rpg-engine/sidecar@3.9.0","maintainers":[{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"}],"homepage":"https://mcp-tool-shop-org.github.io/ai-rpg-engine/","bugs":{"url":"https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"},"dist":{"shasum":"7cecedd686af4d20436a49d17ec296a1a9b2152a","tarball":"https://registry.npmjs.org/@ai-rpg-engine/sidecar/-/sidecar-3.9.0.tgz","fileCount":38,"integrity":"sha512-dguIkgO52oBhBvwnq7sR9aNpkriNSrOHzW/WfkGkAL29X1rp415g9HY0ol13ur5XsOtcQ6yNROlHhvNWAqOvwA==","signatures":[{"sig":"MEUCIDXgS8BngWJJYDmPDQvHcNuO/7BXa8wOQhjrGRtaHpDkAiEA03rQXWbo3S5m0l08NQSGDAnLxK3zeD8vBenrwh1hVAg=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-rpg-engine%2fsidecar@3.9.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":233364},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"281a7e5a42951dd2a76b39cb713f13b8768d3098","scripts":{"test":"vitest run","build":"tsc"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ce01d16a-e466-44c8-b23a-0ebd8fca88e1"}},"repository":{"url":"git+https://github.com/mcp-tool-shop-org/ai-rpg-engine.git","type":"git","directory":"packages/sidecar"},"_npmVersion":"11.19.1","description":"JSON-RPC sidecar for the AI RPG Engine — one authoritative sim process, N rendering clients","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@ai-rpg-engine/core":"*"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sidecar_3.9.0_1788171459759_0.7575079849182254","host":"s3://npm-registry-packages-npm-production"}},"3.10.0":{"name":"@ai-rpg-engine/sidecar","version":"3.10.0","keywords":["rpg","json-rpc","sidecar","game-engine","protocol","deterministic"],"author":{"name":"mcp-tool-shop"},"license":"MIT","_id":"@ai-rpg-engine/sidecar@3.10.0","maintainers":[{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"}],"homepage":"https://mcp-tool-shop-org.github.io/ai-rpg-engine/","bugs":{"url":"https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"},"dist":{"shasum":"4d6df7a46854aa3eaae59e8b445fc3f16c233d97","tarball":"https://registry.npmjs.org/@ai-rpg-engine/sidecar/-/sidecar-3.10.0.tgz","fileCount":38,"integrity":"sha512-4AdfT6LeWOtWpN/PQcDH6+oxrAn2fb+mwcCFge7m5slTItUi330aCZz+h3QQg3aHH0ds50bOumkbS/zgH0xbZw==","signatures":[{"sig":"MEQCIFU/y1BP6EY7ARhU3PvDAWqjms1sTCSPn8oWTGMTc73DAiAeTOOx76zFTsiD3zS30keBtS4RPY2uf5sVwm2c2puSzw==","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-rpg-engine%2fsidecar@3.10.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":240630},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"b84e470eccb8320f5fdb46f1ee8d8d9d42ac9b20","scripts":{"test":"vitest run","build":"tsc"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ce01d16a-e466-44c8-b23a-0ebd8fca88e1"}},"repository":{"url":"git+https://github.com/mcp-tool-shop-org/ai-rpg-engine.git","type":"git","directory":"packages/sidecar"},"_npmVersion":"11.19.1","description":"JSON-RPC sidecar for the AI RPG Engine — one authoritative sim process, N rendering clients","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@ai-rpg-engine/core":"*"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sidecar_3.10.0_1788204690227_0.4688297532972858","host":"s3://npm-registry-packages-npm-production"}},"3.11.0":{"name":"@ai-rpg-engine/sidecar","version":"3.11.0","keywords":["rpg","json-rpc","sidecar","game-engine","protocol","deterministic"],"author":{"name":"mcp-tool-shop"},"license":"MIT","_id":"@ai-rpg-engine/sidecar@3.11.0","maintainers":[{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"}],"homepage":"https://mcp-tool-shop-org.github.io/ai-rpg-engine/","bugs":{"url":"https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"},"dist":{"shasum":"c25319ca19369fc70813bf352ee21851b3b06ff9","tarball":"https://registry.npmjs.org/@ai-rpg-engine/sidecar/-/sidecar-3.11.0.tgz","fileCount":38,"integrity":"sha512-Q26CI4l6M+U0E7hJeHXVuZs7Nkl269+OW1LPdAK7OKSD/JE0jdz+bD06qw4sgbumG9gYhHVS3T5/qraNNNOm6A==","signatures":[{"sig":"MEYCIQD+QBESOrDRq1XxzkSkql/3Nz+h1k3rM9Magy81YcgovgIhAJxeHTljacRtR0MXTMHDsyMAhzKeSsVLQY++S6g1EFa6","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-rpg-engine%2fsidecar@3.11.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":240630},"main":"./dist/index.js","type":"module","types":"./dist/index.d.ts","engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"acbc2d1d3453d7af4bec321c3f6f4fba7f383aed","scripts":{"test":"vitest run","build":"tsc"},"_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ce01d16a-e466-44c8-b23a-0ebd8fca88e1"}},"repository":{"url":"git+https://github.com/mcp-tool-shop-org/ai-rpg-engine.git","type":"git","directory":"packages/sidecar"},"_npmVersion":"11.19.1","description":"JSON-RPC sidecar for the AI RPG Engine — one authoritative sim process, N rendering clients","directories":{},"_nodeVersion":"24.19.0","dependencies":{"@ai-rpg-engine/core":"*"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"tmp":"tmp/sidecar_3.11.0_1788246523453_0.5952297534800248","host":"s3://npm-registry-packages-npm-production"}},"3.12.0":{"_id":"@ai-rpg-engine/sidecar@3.12.0","bugs":{"url":"https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"},"dist":{"shasum":"9369467c7566eb942cb28dc2b10599473fe4a263","tarball":"https://registry.npmjs.org/@ai-rpg-engine/sidecar/-/sidecar-3.12.0.tgz","fileCount":42,"integrity":"sha512-HoW8+wvRx0q3D0Hs6A/qX92j7Yk3Q7uuUZs05maFAGbtesCon0uzdk03DHa3XdSgjuwm6AR3QHnj8OuUoumXwQ==","signatures":[{"sig":"MEUCIQDXa8z6va6PRO/y1DAE9BOjIBC/tohfCOQeysPbQv9i4gIgJKKw153lNGSbIgXTLsYNcc+3rU89Oif0bid75yum6Qw=","keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U"},{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCIC221dCL7p666elWKc4mQTwb3voybVBCsbLv+AjKHFbIAiEAnxn1QTLrNtY4klcTaqdGrQzBVmuG/4nQQdOKJqj/0I4="}],"attestations":{"url":"https://registry.npmjs.org/-/npm/v1/attestations/@ai-rpg-engine%2fsidecar@3.12.0","provenance":{"predicateType":"https://slsa.dev/provenance/v1"}},"unpackedSize":253201},"main":"./dist/index.js","name":"@ai-rpg-engine/sidecar","type":"module","types":"./dist/index.d.ts","author":{"name":"mcp-tool-shop"},"engines":{"node":">=20"},"exports":{".":{"types":"./dist/index.d.ts","import":"./dist/index.js"}},"gitHead":"bf74871b46a02b5fb1bb333cec68d305c5fe7d7c","license":"MIT","scripts":{"test":"vitest run","build":"tsc"},"version":"3.12.0","_npmUser":{"name":"GitHub Actions","email":"npm-oidc-no-reply@github.com","trustedPublisher":{"id":"github","oidcConfigId":"oidc:ce01d16a-e466-44c8-b23a-0ebd8fca88e1"}},"homepage":"https://mcp-tool-shop-org.github.io/ai-rpg-engine/","keywords":["rpg","json-rpc","sidecar","game-engine","protocol","deterministic"],"repository":{"url":"git+https://github.com/mcp-tool-shop-org/ai-rpg-engine.git","type":"git","directory":"packages/sidecar"},"_npmVersion":"11.19.1","description":"JSON-RPC sidecar for the AI RPG Engine — one authoritative sim process, N rendering clients","directories":{},"maintainers":[{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"}],"_nodeVersion":"24.20.0","dependencies":{"@ai-rpg-engine/core":"*","@ai-rpg-engine/presentation":"*","@ai-rpg-engine/audio-director":"*","@ai-rpg-engine/soundpack-core":"*"},"_hasShrinkwrap":false,"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/sidecar_3.12.0_1789973407370_0.17283340422654447"}}},"time":{"created":"2026-08-31T06:06:54.301Z","modified":"2026-09-21T06:50:07.808Z","0.0.0":"2026-08-31T06:06:54.643Z","3.8.1":"2026-08-31T06:14:57.627Z","3.9.0":"2026-08-31T10:17:39.884Z","3.10.0":"2026-08-31T19:31:30.363Z","3.11.0":"2026-09-01T07:08:43.591Z","3.12.0":"2026-09-21T06:50:07.467Z"},"bugs":{"url":"https://github.com/mcp-tool-shop-org/ai-rpg-engine/issues"},"author":{"name":"mcp-tool-shop"},"license":"MIT","homepage":"https://mcp-tool-shop-org.github.io/ai-rpg-engine/","keywords":["rpg","json-rpc","sidecar","game-engine","protocol","deterministic"],"repository":{"url":"git+https://github.com/mcp-tool-shop-org/ai-rpg-engine.git","type":"git","directory":"packages/sidecar"},"description":"JSON-RPC sidecar for the AI RPG Engine — one authoritative sim process, N rendering clients","maintainers":[{"name":"mikefrilot","email":"mikeyfrilot@gmail.com"}],"readme":"<p align=\"center\">\n  <img src=\"https://raw.githubusercontent.com/mcp-tool-shop-org/brand/main/logos/ai-rpg-engine/readme.png\" width=\"400\" alt=\"AI RPG Engine\">\n</p>\n\n<p align=\"center\">\n  <a href=\"https://www.npmjs.com/package/@ai-rpg-engine/sidecar\"><img src=\"https://img.shields.io/npm/v/@ai-rpg-engine/sidecar.svg\" alt=\"npm\"></a>\n  <a href=\"https://github.com/mcp-tool-shop-org/ai-rpg-engine/actions/workflows/ci.yml\"><img src=\"https://github.com/mcp-tool-shop-org/ai-rpg-engine/actions/workflows/ci.yml/badge.svg\" alt=\"CI\"></a>\n  <a href=\"https://github.com/mcp-tool-shop-org/ai-rpg-engine/blob/main/LICENSE\"><img src=\"https://img.shields.io/badge/License-MIT-yellow.svg\" alt=\"License: MIT\"></a>\n  <a href=\"https://mcp-tool-shop-org.github.io/ai-rpg-engine/\"><img src=\"https://img.shields.io/badge/Landing_Page-live-blue\" alt=\"Landing Page\"></a>\n</p>\n\n# @ai-rpg-engine/sidecar\n\n**One authoritative simulation process. Any number of rendering clients.**\n\nRun the AI RPG Engine as a JSON-RPC server over stdio, and talk to it from a\nrenderer that is not a terminal — a game client, an editor, a debug overlay, a\ntest harness. The client submits intents; the simulation decides; events come\nback tick-stamped with a per-tick state hash.\n\nThe point is what stays true across the process boundary: a scripted session run\nover the wire produces a **byte-identical** event stream and the same end-state\nhash as the same session run in-process.\n\n## Install\n\n```bash\nnpm install @ai-rpg-engine/sidecar\n```\n\n## Run a simulation as a server\n\n```bash\nai-rpg-engine sidecar chapel-threshold --seed 71\n```\n\n`stdout` carries framed protocol messages only; diagnostics go to `stderr`.\n\n## Talk to it\n\n```ts\nimport { MessageReader, encodeMessage, METHODS, connectSocketClient } from '@ai-rpg-engine/sidecar';\n\n// 1. Handshake. Capabilities are exchanged — there is no protocol version.\nawait request(METHODS.INITIALIZE, {\n  clientName: 'my-renderer',\n  clientVersion: '1.0.0',\n  capabilities: { notifications: true, hashes: true, canonicalHashes: true },\n});\n\n// 2. Load the world. A snapshot is a delta from an empty baseline, produced by\n//    the same serializer as every incremental update. Call this before listening\n//    for sim/tick — incremental ticks are withheld until SNAPSHOT (snapshotSeq).\nconst snap = await request(METHODS.SNAPSHOT);\nlet world = applyPatches({}, snap.delta);\n\n// 3. Submit an intent. The simulation validates it; the client never decides.\nconst result = await request(METHODS.SUBMIT_ACTION, { verb: 'move' });\n\n// 4. Tick notifications arrive as server PUSH, carrying events, a state delta,\n//    and the hash you use to detect staleness. Drop ticks whose snapshotSeq is\n//    below the last applied snapshot.\n```\n\nA JS host attaching over TCP should use the exported helper, not copy test glue:\n\n```ts\nconst { client } = await connectSocketClient(7731);\nawait client.initialize({ notifications: true, hashes: true, canonicalHashes: true });\nawait client.snapshot();\n```\n\n### Godot attach (TCP, not stdio pipes)\n\nGDScript subprocess pipes are documented-buggy upstream (godot#102340). Attach\nover localhost TCP — the same wire Godot's own editor uses. The shipped host kit\nlives in `gdscript/` (`SidecarFraming` + `SidecarAttachClient`).\n\n```bash\nai-rpg-engine sidecar chapel-threshold --seed 71 --listen 7731\n```\n\n```gdscript\nvar client := SidecarAttachClient.new()\nclient.connect_to_host(\"127.0.0.1\", 7731)\nvar init_id := client.initialize({\n  \"notifications\": true,\n  \"hashes\": true,\n  \"canonicalHashes\": true,  # cross-language hash; do not JSON.stringify\n  \"writes\": true,           # false = observer overlay (ticks only)\n  \"listActions\": true,\n  \"presentation\": true,     # presentAll + FOW; omit for raw ticks\n  \"audio\": true,            # felt payload: AudioCommand[] + SpeakerCue + UiEffects\n})\n# await client.completed for init_id, then:\nclient.snapshot({ \"omitEventLog\": true })  # replay covers presentation\nclient.advance(1)  # sends METHOD_ADVANCE with a JSON-RPC id\n# per-frame: client.poll()  # watches StreamPeerTCP.get_status(); STATUS_NONE/ERROR emits closing and clears _pending\n# Save is Engine.serialize (rngState + actionLog), not a SNAPSHOT delta:\n# client.save() / client.load_save(serialized)\n```\n\nThe shipped Godot 4 host is [`ai-rpg-stage`](https://github.com/mcp-tool-shop-org/ai-rpg-stage). Play camera is 2:1 dimetric (TileMapLayer 256×128), not a graph of postage-stamp rooms. Occupancy in the sim is still a **zone id**: a click inside the current zone walks as presentation; a click in a neighbour zone submits `move`. `felt` is never hashed. Do not put `CharacterBody2D` on this wire. Handbook: [Visual Clients](https://mcp-tool-shop-org.github.io/ai-rpg-engine/handbook/66-visual-clients/).\n\n## Design\n\n| Property | Shape |\n|---|---|\n| **Commands in, events out** | The client submits intents; the simulation resolves them. Nothing the client knows reaches the sim except as an explicit command. |\n| **Capabilities, not versions** | `initialize` exchanges capability flags, so a partial client and a fuller server interoperate without either bumping a number. |\n| **Push, not poll** | Derived state arrives as tick-stamped notifications. Clients never gate tick advancement. |\n| **One serializer** | A snapshot is `diff({}, state)` — the incremental path against an empty baseline. Snapshot and stream cannot diverge, because there is only one of them. |\n| **Per-tick hashes** | Clients detect staleness and report it. They never correct the simulation. `SidecarClient` records `stalenessReports` and fires an optional `onStale` hook (and a stderr line if you omit the hook). Hosts must call `snapshot()` on staleness and re-render from that delta — never patch the mirror locally. |\n| **Strict in, tolerant out** | Unknown commands *and* unknown command fields are refused: a silently dropped field means the sim ran a different intent than you submitted. Events only ever gain fields, so a client that ignores what it does not know loses nothing. Methods are request/response: a known method with no JSON-RPC `id` is refused and does not run. `shutdown` is the one fire-and-forget exception (an orderly stop should still run if the id was dropped). |\n| **Additive-only events** | With a reserved graveyard, so a removed field's name is never recycled with a new meaning. |\n| **Side-effect-free preview** | Run a command on a copy, get the events, discard. The world hash before equals the world hash after. |\n\nTransport is a constructor argument. `stdio.ts` is the only module that names\none, so a socket server is the same two calls with a different pair of streams.\nAttach (TCP) logs framing errors, bind address/port, accepts, cap-refusals, and\ndisconnects to stderr by default — the same visibility stdio already had for\nframing. Pass a hook to replace a default; you do not have to opt the library\ninto logging.\n\n`SidecarClient.request` times out (30s default) and `sim/closing` / `disconnect()`\nreject every in-flight Promise with `SESSION_CLOSED`, so a dead peer cannot hang\nthe renderer.\n\n## Methods\n\n| Method | Purpose |\n|---|---|\n| `initialize` | Capability handshake. Required first. Returns `packId` / `playerId` / `locationId` additively, plus `packIntake` (the pack gate's `dropped[]`/`advisories`) when there is something to report — cleared on `load`. |\n| `snapshot` | The whole world, as a delta from empty. Optional `omitEventLog` / `collections` window the resync. |\n| `submitAction` | Submit a player intent. Optional `actorId` (else `world.playerId`). Observers (`writes: false`) are refused. |\n| `advance` | Advance the world without a player action. Observers refused. |\n| `preview` | Evaluate a command with no side effects. |\n| `replay` | Re-emit a closed tick window. Optional `typePrefix` / `actorId` / `limit` via `queryEvents`. |\n| `listActions` | Legal-action catalog (`getAvailableActionsFor`). Observers may call it. |\n| `save` | `Engine.serialize` checkpoint (rngState + actionLog). Not a SNAPSHOT delta. Writers only. |\n| `load` | `Engine.deserialize`, rebase every live session, push a snapshot-shaped baseline. Writers only. |\n| `shutdown` | Orderly stop. May omit `id` (fire-and-forget). Observers refused. |\n\nNotifications: `sim/tick` (events + delta + hash + `snapshotSeq`; `canonicalHash` when negotiated; `felt` when `audio` is on), `sim/closing`. Writers play `felt` from the submit/advance result and ignore `sim/tick.felt` so overlay stings do not double. Observers never get those RPC results; they play the tick.\n\n`initialize` capabilities: `notifications`, `hashes`, `canonicalHashes` (second hash, never a replacement for the JS `hash`), `writes` / `role` (`writer` \\| `observer`), `listActions`, `presentation` (tick/replay events are `engine.presentAll`; hidden events dropped), `audio` (submit/advance/tick carry a `felt` payload of cue-ids, an optional spoken line, and UI effects — presentation-only, never hashed). Incremental ticks are withheld until that session has served `snapshot`. Two `writes: true` sessions serialize mutations by session-order then JSON-RPC id.\n\n## License\n\nMIT\n\n---\n\nBuilt by <a href=\"https://mcp-tool-shop.github.io/\">MCP Tool Shop</a>\n","readmeFilename":"README.md"}