Skip to main content
Glama
README.md
# fmod-mcp

An MCP server that lets an AI coding agent drive **FMOD Studio**: import audio, create events, wire instruments, place effects on buses, set up sends/returns, manage parameters, and build banks. It does this by speaking to Studio's built-in JavaScript scripting terminal over TCP (port 3663).

**v0.2: 35 tools, 143 tests passing (106 unit + 37 live, plus 1 gated persist test).** See [CLAUDE.md](CLAUDE.md) for the tool catalog, [docs/effects.md](docs/effects.md) for the effect-parameter reference, [docs/troubleshooting.md](docs/troubleshooting.md) when something breaks, and [examples/](examples/) for worked walkthroughs.

Built for use with [Claude Code](https://claude.com/claude-code), but works with any MCP-compatible client.

## Requirements

- FMOD Studio 2.02+ (the scripting terminal has been stable across recent versions)
- Python 3.11+
- A running FMOD Studio instance with the target project open

## Install

```bash
git clone https://github.com/jmperez127/fmod-mcp.git
cd fmod-mcp
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
```

## Register with Claude Code

Run this from inside the cloned `fmod-mcp` directory (so `$(pwd)` resolves correctly):

```bash
claude mcp add fmod -s user -- "$(pwd)/.venv/bin/python" -m fmod_mcp
```

The `--` ends `claude mcp add`'s flag parsing so `-m fmod_mcp` is treated as
arguments to Python. `-s user` registers the server for every Claude Code
session on your machine; drop it for a project-local registration.

Alternatively, if you prefer a globally-callable shim, install via [pipx]:

```bash
pipx install .
claude mcp add fmod -s user fmod-mcp
```

[pipx]: https://pipx.pypa.io/

Verify:

```bash
claude mcp list
```

## Configure host/port (optional)

Defaults to `127.0.0.1:3663`. Override with environment variables:

```bash
export FMOD_MCP_HOST=127.0.0.1
export FMOD_MCP_PORT=3663
```

## Enable TCP scripting in Studio

FMOD Studio's scripting terminal listens on TCP/3663 by default. If it's disabled:

1. Open FMOD Studio
2. `Edit` → `Preferences` (or `FMOD Studio` → `Preferences` on macOS)
3. Look for `Scripting` / `Terminal` settings
4. Enable TCP listener, note the port

## Quick smoke test

With FMOD Studio running and a project open:

```
> ping
{ ok: true, version: { productVersion: 2, majorVersion: 2, minorVersion: 20, ... } }

> list_banks
[ { path: "bank:/Master", guid: "...", name: "Master" }, ... ]
```

## Worked examples

The [examples/](examples/) directory has prompt-style walkthroughs you can paste into a Claude Code session:

| File | Scenario |
|---|---|
| [add_one_sfx.md](examples/add_one_sfx.md) | Minimum pipeline: import → event → sound → save → build |
| [batch_import_sfx.md](examples/batch_import_sfx.md) | Loop the above over a folder of wavs |
| [add_reverb_to_bus.md](examples/add_reverb_to_bus.md) | Reverb return + global send (with parameter reference) |
| [sidechain_compression.md](examples/sidechain_compression.md) | Music-ducks-to-VO routing |
| [parameter_driven_volume.md](examples/parameter_driven_volume.md) | Local game parameter for an event |
| [cleanup_unused_audio.md](examples/cleanup_unused_audio.md) | Find and delete orphan audio in the bin |

## Files it writes

- `~/.cache/fmod-mcp/commands.log`: every JS snippet sent to Studio, timestamped by request ID. Audit trail + replay source.

## Testing

Unit tests run without Studio (mock-based):

```bash
pytest -q
# 106 passed, 38 skipped (live tests)
```

Live tests require FMOD Studio running with any project open:

```bash
FMOD_MCP_LIVE=1 pytest -q
# 143 passed, 1 skipped (persist-gated)
```

The persist-gated save+build verification additionally writes to disk; opt in explicitly:

```bash
FMOD_MCP_LIVE=1 FMOD_MCP_LIVE_PERSIST=1 pytest tests/live/test_save_build_live.py
```

Live tests use a per-test scratch folder under `event:/__mcp_test_scratch__/<hex>/` and clean up via `studio.project.deleteObject` on tear-down. A session-scoped sweep also runs at start AND end so an interrupted run doesn't leave orphans.

## When things break

See [docs/troubleshooting.md](docs/troubleshooting.md) for the common failure modes and their fixes. The short version:

1. Check `~/.cache/fmod-mcp/commands.log` for the exact JS that went out.
2. Paste it into Studio's own Scripting window (`Window` → `Scripting` in the Studio GUI) and iterate.
3. Once working, patch the corresponding JS template in `fmod_mcp/tools/*.py`.

For anything not covered by a named tool, use `run_js`:

```
> run_js return studio.project.model.Event.findInstances().length;
42
```

## Layout

```
fmod_mcp/
├── studio_client.py   # TCP/3663 client. Single persistent connection, sentinel-framed IIFE protocol
├── server.py          # FastMCP tool registration, stdio transport
├── __main__.py        # python -m fmod_mcp
└── tools/
    ├── discovery.py   # ping, list_banks, list_events, list_buses, get_event
    ├── audio.py       # import_audio, delete_audio, move_audio
    ├── events.py      # create_event, add_single_sound, add_multi_sound,
    │                  # set_event_property, assign_to_bank, assign_to_bus,
    │                  # delete_event, delete_folder, rename_event, move_event,
    │                  # add_local_parameter, add_global_parameter
    ├── effects.py     # list_effect_types, add_effect, list_effects, get_effect,
    │                  # set_effect_param, remove_effect, bypass_effect
    ├── routing.py     # add_return, remove_return, list_returns,
    │                  # add_send, list_sends, remove_send, set_send_level
    ├── project.py     # save_project, build_banks, deploy_banks
    └── escape.py      # run_js

tests/
├── (mock-based unit tests)
└── live/              # opt-in via FMOD_MCP_LIVE=1; auto-skip when port 3663 isn't reachable
```

## License

[MIT](LICENSE) © 2026 jmperez127.

TDQS

B3.2/5.0

Scored across 21 tools

Disambiguation4/5

Most tools target distinct resources and actions. However, create_event already includes assignment to bank and bus, creating some overlap with assign_to_bank and assign_to_bus.

Naming Consistency5/5

All tools follow a consistent verb_noun pattern (e.g., add_effect, list_events, set_event_property). Prepositions in assign_to_bank are acceptable and consistent.

Tool Count4/5

21 tools is slightly high but still well-scoped for the FMOD Studio domain. Each tool serves a distinct purpose without excessive redundancy.

Completeness3/5

Core workflows like event creation, effect management, and building are covered. Notable gaps include no delete operations for events or sounds, and no update beyond property setting.