# Synapse

> Talk to Houdini in plain English. SYNAPSE lives inside Houdini's own Python and turns your words into real, undoable nodes - one Ctrl+Z reverses a whole operation, and a human approves anything risky. It says 'unknown' instead of guessing. 120+ tools, 6,000+ tests, Houdini 22.0.400. Limitations documented, not omitted.

- **Type:** MCP server
- **Install:** `agentstack add mcp-josephoibrahim-synapse`
- **Verified:** Yes — security-reviewed for prompt injection and unsafe behavior
- **Seller:** [JosephOIbrahim](https://agentstack.voostack.com/s/josephoibrahim)
- **Installs:** 0
- **Category:** [AI & ML](https://agentstack.voostack.com/c/ai-and-ml)
- **Latest version:** 0.1.0
- **License:** MIT
- **Upstream author:** [JosephOIbrahim](https://github.com/JosephOIbrahim)
- **Source:** https://github.com/JosephOIbrahim/Synapse

## Install

```sh
agentstack add mcp-josephoibrahim-synapse
```

Requires the [AgentStack CLI](https://agentstack.voostack.com/docs/cli). Works with Claude Code, Cursor, and any MCP-compatible agent.

## About

An AI agent that runs inside Houdini — not beside it.

Read Known limitations first — this repo's habit is saying what doesn't work.

SYNAPSE lives in Houdini's own Python interpreter and calls hou.* directly.No external bridge, no RPC hop, no second copy of the scene.

v5.45.1 · Houdini 22.0.400 (doc pin — the symbol gate re-stamps per running build) · Python 3.13 · USD 0.26.5 · PySide6

---

## For artists — the one-minute version

**You type what you want. Real nodes appear in your scene — built, wired, and named.**
"Give me a Vellum cloth setup on this mesh" becomes actual nodes, not a chat answer.

**One Ctrl+Z undoes the whole thing.** Every operation is grouped, so a ten-node
build reverses in a single undo. You can always get your scene back.

**It asks before anything risky.** Writing files, big changes — a human clicks approve.
It never bakes gigabytes to disk on its own.

**It says "I don't know" instead of guessing.** Unmeasured things are reported as
unknown, never invented. When something isn't supported yet, it tells you so.

**It is not magic and not a render button.** Read [Known limitations](#known-limitations) —
this project's habit is saying what doesn't work before you find out mid-shot.

---

## Watch it work

[](https://vimeo.com/1216840044)

*SYNAPSE in practice: plain English in, undoable nodes out.*

---

## Runs your model

Five engines behind one seam. The roster and the producer path are the same thing: `python/synapse/panel/providers/`.

**Ollama needs no API key, and nothing leaves the machine.** SYNAPSE talks to your local server at its default address, `http://localhost:11434`.

**Your pick persists.** Engine choice is saved to `.synapse/panel_settings.json` and survives restarts.

---

## The one design choice

Everything else follows from where the agent lives.

```mermaid
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#4d4d4d','primaryTextColor':'#FFFFFF','primaryBorderColor':'#000000','lineColor':'#000000','textColor':'#FFFFFF','secondaryColor':'#404040','tertiaryColor':'#333333','clusterBkg':'#333333','clusterBorder':'#000000','edgeLabelBackground':'#333333','nodeTextColor':'#FFFFFF'}}}%%
flowchart LR
    subgraph OUT["outside-in"]
        H1[Houdini] -->|whole scene, every turn| C1[cloud model]
        C1 -->|answer| H1
    end
    subgraph IN["inside-out — SYNAPSE"]
        H2[Houdini] --> A[agent in-process]
        A -->|only what you asked about| C2[cloud model]
        C2 --> A
        A -->|acts in place| H2
    end
```

**Measured, not claimed.** Grounding payload across a 13 → 25,850 node ladder rises 443 → 113,411 tokens. That is **256×** — not flat. The same probe without depth bounds rises 2,788×.

The honest statement: **cost scales with what you ask about, not with the size of your scene.**

The mechanism is *bounded depth*. Single-call coverage falls to 10% on the largest scenes, with 100% completeness inside the window it reads. There is currently **no delta path** — every inspect is a full re-read.

*Producer: `harness/notes/token_bench/`, 2026-07-27. Proxy tokenizer, no live-model arm.*

---

## Known limitations

Read this here rather than discover it mid-shot.

**`synapse_inspect_scene` does not return over the external MCP surface.** It hangs to the idle timeout. The function itself is instantaneous when called directly — 0.08s for the whole of a 5,764-node scene — so the fault is in the main-thread marshal under MCP, not in introspection. **The panel's WebSocket path is unaffected** and is demonstrated working on that same scene.

**The retrieval corpus is Houdini 21 documentation.** Symbols and node types are H22 and verified; the prose is not yet converted. Most consequential for Copernicus.

**No delta path.** Every inspect is a full re-read. Re-asking about the same thing costs the same again.

**A render can be stopped, but not from `RopNode`.** No cancel method exists there. `hou.ActiveRender` is documented, `#status: ni`, and absent at runtime. SYNAPSE now stops renders through `rkill` (`render_stop`), with two limits worth knowing:

- Only **background** renders can be stopped — those are the only ones `rps` can see. A foreground, in-process render is not reachable.
- Only **Karma/husk** renders can be stopped *by ROP path*. A **mantra** render shows up in `rps` as the bare word `mantra` with no node identity, so SYNAPSE refuses to guess which one is yours and asks for an explicit PID instead.

**Stopping a mantra render leaves a valid-looking but empty frame.** mantra writes the EXR header to the real output path immediately and keeps pixels in a `.mantra_checkpoint` sidecar, so a stopped render leaves a ~1KB EXR that opens fine and contains no image. A "does the file exist?" check will pass it. Detect it by the leftover `.mantra_checkpoint`, or by a header missing `renderTime`. **Stopping a Karma render is safe** — husk only writes the declared output on completion, so it simply never appears.

**The chat-time UI grip is closed (v5.40.1).** Mid-chat node-selection freezes — the bridge-down Qt-fallback class — no longer fire; tool calls and context-gather run off the main thread. See *The chat freeze, and what fixed it* below. Distinct from the render freezes covered there.

**`execute_python` results are stringified over the live WS.** A dict comes back as its Python repr (`"result": str(result)`). Parse with `ast.literal_eval`; a handler-side fix is queued but needs a Houdini restart to go live, so the client-side parse is the current contract. *Found by the bench's first live contact, 2026-08-02.*

**The PDG rollback has never executed.** `bridge.py:1718` passes `remove_files=`; the real keyword is `remove_outputs`. It raises `TypeError` every time.

**41 node types in use are deprecated** — 39 of them deprecated in the docs while the runtime says nothing, so a probe alone cannot see them.

**Emergency halt is surfaced, and the shipped mechanism alone was not enough.** It now lives in the panel's `⋯` overflow as a control distinct from Stop. Worth knowing why it is not just a button on the old function: `EmergencyProtocol.trigger_emergency_halt` walks **`/obj` only**. Probed against a real cook at `/tasks/h3b_topnet` on 22.0.368 it returned `ALL_OPERATIONS_HALTED` in 0.0s and the cook was still running three seconds later — and `/tasks` is where TOP networks live by default. The halt handler therefore does its own scene-wide sweep and reports the three results separately: what the bridge halt did, which TOP networks it then cancelled, and which background renders are **still running** (it does not kill those — `rkill *` would reach renders this session never started).

**Node grounding is uneven, and the shape of it changed.** 603 Copernicus, LOP and Cop2 types now carry build-pinned reference from `nodes.zip` — but that is *what a node is*, not *how to use it together*. Workflow prose is still H21. And 88 live types ship with no help page at all, so documentation cannot ground them by any method. 37.9% of LOP parameters are documented — the ceiling from documentation alone.

**Token figures are proxy-measured**, and no genuine outside-in comparison has been built.

---

## What it knows, and where that comes from

This matters more than the feature list, and it is the thing to check first.

```mermaid
%%{init: {'theme':'base','themeVariables':{'primaryColor':'#4d4d4d','primaryTextColor':'#FFFFFF','primaryBorderColor':'#000000','lineColor':'#000000','textColor':'#FFFFFF','secondaryColor':'#404040','tertiaryColor':'#333333','clusterBkg':'#333333','clusterBorder':'#000000','edgeLabelBackground':'#333333','nodeTextColor':'#FFFFFF'}}}%%
flowchart TD
    K[what SYNAPSE knows] --> S[symbols and node types]
    K --> N[H22 node reference]
    K --> P[prose and how-to]
    S --> S1["h22_symbol_table.json35,908 symbols, re-stamped per build"]
    S --> S2["connectivity_22.jsonlop_solaris_knowledge_22.json"]
    N --> N1["rag/corpus/h22_nodes.json603 live types, 22.0.368"]
    P --> P1["rag/skills/houdini21-referenceH21 documentation"]
    S1 --> OK["verified against the running buildgate goes STALE if they diverge"]
    S2 --> OK
    N1 --> OK
    P1 --> GAP["NOT yet converted to H22"]
```

**Symbols are H22.** The table is stamped against the running build, and `phantom_gate_status` goes stale if they diverge.

**Node reference is H22.** Extracted from `nodes.zip` — the reference that ships *with the build* — and every entry validated by probing its documented type against the running catalogue. **Only matched entries are written**, so a phantom is never stored rather than filtered at read time.

**Prose is H21.** The retrieval corpus is Houdini 21 documentation, accurately labelled as such. If you ask a how-to question, SYNAPSE may answer from H21 material and tell you so.

**And the Copernicus gap is now closed on the node axis.** It was the sharpest hole in this diagram — Copernicus barely existed in H21, so prose could never cover it. Ask about `chromakey` or `grunge_rust` by name and you get a build-pinned answer. Ask *how to composite* and you still get H21 prose.

---

## What it does

**Builds networks.** Ask for a Solaris scene, a material graph, a COP chain — it wires the nodes and tells you what it chose.

**Explains itself.** Every mutation records what it did and why.

**Stays on the main thread.** All `hou.*` calls marshal to Houdini's main thread.

**Says no when it can't.** This took four fixes in one day (2026-08-02), all the same disease — a green light that couldn't report failure. `get_health` now carries `write_plane` (it used to say *healthy* over a dead write path); `composition_valid` carries a real verdict (it had **zero** assignment sites — an integrity anchor that could never fail); operations that fail *before* validation say so instead of inheriting "ran and passed"; and value-only edits the reduced hash cannot see are **counted** as `unobservable_deltas` rather than vanishing. *Producers: commits `68ab53e`, `57c4ec6`, `73284e1`; pinned by `tests/test_write_plane_health.py` (26), `tests/test_stage_exceeds_cache_and_composition_valid.py` (13), `tests/test_r306_reduced_mode_surfacing.py` (19).*

**Writes memory on a fresh scene.** The first `memory_write` on an unsaved scene used to die with `WinError 5` — `$JOB` points into Houdini's install `bin/`, which the seat can't write. Scene memory now resolves a writable address (discovery still reads the raw `$JOB` root, so studio show-configs keep working). Verified end-to-end on the live seat, twice, against a captured cold-boot baseline. *Producer: `scripts/live_probes/probe_g1_acceptance_ws.py` → `VERDICT: PASS`.*

**Refuses to boot on a render node** — *narrowly.* `hou.isUIAvailable()` gates the daemon, the Fork Bomb guard. But it protects a component with no production callers today while other surfaces boot headless. A guard that exists, not a guarantee that holds.

### The full claim, unpacked

This is the package description in long form — everything the one-liner compresses.

**115 tools, two paths.** The full safety set (undo-wrapped, reversible, provenance-recorded) rides the audited `/mcp` bridge path. The direct `/synapse` path is RBAC-gated, main-thread-marshalled execution with observe-only provenance. Scene mutations are undo-wrapped and reversible. Filesystem and network effects of executed code are not.

**A registry-wide truth contract.** A result may not claim an outcome the handler did not observe.

**A self-improving utility flywheel.** Proposed node-graphs are validated against probe-verified Houdini truth — node wiring plus Solaris/LOP context — *before* they build.

**A five-engine chat panel.** Switch between Claude, Google Gemini, NVIDIA Nemotron, local Ollama, and any custom OpenAI-compatible endpoint. Raw-stdlib providers, no vendor SDK.

**Pipeline citizenship.** Tokens stay raw, per-frame render paths, OCIO color-managed previews, per-show config.

**Studio operability.** Rotating logs, `synapse_doctor` diagnostics + bundle, env-var conformance, bounded autonomy with a stop control that takes effect between operations, an upgrade runbook, egress + key-provisioning docs.

**A two-tier audit trail.** Tier-0 Floor hook + the agent.usd Ledger.

**Crash-atomic escrowed memory.** And a process-wide stall-detection chain (detect → breaker → emergency-halt report) that reports and degrades rather than unblocking a parked session.

Verified end-to-end on Houdini 22.0.368. 22.0.400: symbol-stamped 2026-08-09 (35,908 symbols, gate armed); e2e re-verification pending — see `docs/SUPPORT_MATRIX.md`.

---

## Install

Four steps. The third is the one people miss.

**1 — Clone**

```
git clone https://github.com/JosephOIbrahim/Synapse.git
```

**2 — Package file**

```
python scripts/install_synapse_package.py
```

Writes the package file — `Documents/houdini22.0/packages/synapse.json` — for you, correctly encoded.

SYNAPSE ships **two installers**, and the split matters: `scripts/install_synapse_package.py` installs the package file (this step); `install.py` installs the shelf, panel, and icons. Order: package file first, then `install.py`.

**3 — Verify**

```
python scripts/install_synapse_package.py --verify
```

Read-only. Prints pass/fail per requirement.

**4 — Doctor**

With the server up, run the `synapse_doctor` tool — ask the panel, or call it from any connected MCP client. Diagnostics plus a support bundle (see Studio operability, above). Registered in `mcp_server.py`; implemented in `python/synapse/server/doctor.py`.

Manual install — write the package file by hand

At `Documents/houdini22.0/packages/synapse.json`:

```json
{
    "name": "synapse",
    "enable": true,
    "env": [
        { "var": "SYNAPSE_ROOT", "value": "C:/path/to/Synapse" },
        {
            "var": "PYTHONPATH",
            "value": ["$SYNAPSE_ROOT/python", "$SYNAPSE_ROOT"],
            "method": "prepend"
        }
    ],
    "hpath": "$SYNAPSE_ROOT/houdini"
}
```

### Three things that bite

**Save the JSON without a BOM.** PowerShell's `Set-Content -Encoding utf8` writes one. Houdini's parser rejects it **silently**.

```powershell
# writes a BOM - Houdini will not load this
Set-Content synapse.json $text -Encoding utf8

# no BOM
[System.IO.File]::WriteAllText($path, $text, (New-Object System.Text.UTF8Encoding $false))
```

**`hpath`, not `path`.** On H22 the keyword is `hpath` — SideFX use it exclusively in their own packages. The deprecated `path` still works, which is why nobody notices.

**`PYTHONPATH` needs both entries.** `shared/` lives at the repo root, not under `python/`.

Get any of these wrong and `import synapse` still succeeds, the version still prints, and **the panel never appears.** No error. Just absence.

---

## First prompt

Nothing to set up beyond Install. **Fresh empty scene. No OCIO. No demo scaffold. No harness runner.**

1. Open Houdini — new, empty scene.
2. Open the SYNAPSE panel.
3. Type:

> **Make me simple terrain — a grid displaced with mountain noise.**

This prompt maps to a recipe the panel ships with — `mountain_displace` in `python/synapse/panel/recipe_book.py`: a 100×100 `grid` SOP wired into a `mountain` SOP (height 1.5). Two nodes, one connection.

**What you'll see:** a terrain-like displaced surface in the viewport. That visible bump-scape is the proof the install worked — no test suite required.

Looking for the full staged walkthrough instead? That's `demo/README.md` — the staged demo, which *does* carry pipeline prerequisites (OCIO, the demo hip).

---

## Troubleshooting

**The panel didn't appear.**

Run the doctor first: the `synapse_doctor` tool, callable from any connected MCP client — no panel required (registered in `mcp_server.py`, implemented in `python/synapse/server/doctor.py`).

Why there's no error message to read: get the package file wrong — a BOM, `path` instead of `hpath`, a missing `PYTHONPATH` entry — and `import synapse` still succeeds, the version still prints, and **the p

…

## Source & license

This open-source MCP server is cataloged on AgentStack and links to its original source — we do not rehost the code.

- **Author:** [JosephOIbrahim](https://github.com/JosephOIbrahim)
- **Source:** [JosephOIbrahim/Synapse](https://github.com/JosephOIbrahim/Synapse)
- **License:** MIT

Install and usage instructions live in the source repository linked above.

## Pricing

- **Free** — Free

## Security capabilities

Automated source analysis of v0.1.0 — what this tool can access:

- **Network access:** yes
- **Filesystem access:** no
- **Shell / process execution:** no
- **Environment & secrets:** no
- **Dynamic code execution:** no

*"Yes" means the capability is present in the source — more access means more to trust, not that it is unsafe.*


## Versions

- **0.1.0** — security scan: passed — Imported from the upstream source.

## Links

- Listing page: https://agentstack.voostack.com/l/mcp-josephoibrahim-synapse
- Seller: https://agentstack.voostack.com/s/josephoibrahim
- Browse the marketplace: https://agentstack.voostack.com/browse

---
Listed on AgentStack — the marketplace for AI agent skills and MCP servers. Every listing is security-reviewed. Creators keep 70%.
