livemcp 1.1.0__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- livemcp-1.1.0/.claude/skills/README.md +9 -0
- livemcp-1.1.0/.claude/skills/publish.md +45 -0
- livemcp-1.1.0/.claude/skills/restart-ableton.md +58 -0
- livemcp-1.1.0/.claude/skills/verify.md +49 -0
- livemcp-1.1.0/.gitignore +13 -0
- livemcp-1.1.0/CLAUDE.md +210 -0
- livemcp-1.1.0/LICENSE +21 -0
- livemcp-1.1.0/PKG-INFO +348 -0
- livemcp-1.1.0/README.md +323 -0
- livemcp-1.1.0/pyproject.toml +42 -0
- livemcp-1.1.0/remote_script/LiveMCP/__init__.py +30 -0
- livemcp-1.1.0/remote_script/LiveMCP/browser.py +317 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/__init__.py +33 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/arrangement.py +179 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/clips.py +1122 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/devices.py +627 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/grooves.py +121 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/mixer.py +255 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/session.py +765 -0
- livemcp-1.1.0/remote_script/LiveMCP/handlers/tracks.py +712 -0
- livemcp-1.1.0/remote_script/LiveMCP/server.py +146 -0
- livemcp-1.1.0/scripts/install.py +122 -0
- livemcp-1.1.0/scripts/install.sh +57 -0
- livemcp-1.1.0/scripts/restart_ableton.sh +92 -0
- livemcp-1.1.0/scripts/uninstall.py +74 -0
- livemcp-1.1.0/scripts/uninstall.sh +18 -0
- livemcp-1.1.0/src/livemcp/__init__.py +3 -0
- livemcp-1.1.0/src/livemcp/__main__.py +5 -0
- livemcp-1.1.0/src/livemcp/connection.py +100 -0
- livemcp-1.1.0/src/livemcp/installer.py +155 -0
- livemcp-1.1.0/src/livemcp/remote_script/__init__.py +30 -0
- livemcp-1.1.0/src/livemcp/remote_script/browser.py +317 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/__init__.py +33 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/arrangement.py +179 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/clips.py +1122 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/devices.py +627 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/grooves.py +121 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/mixer.py +255 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/session.py +765 -0
- livemcp-1.1.0/src/livemcp/remote_script/handlers/tracks.py +712 -0
- livemcp-1.1.0/src/livemcp/remote_script/server.py +146 -0
- livemcp-1.1.0/src/livemcp/server.py +35 -0
- livemcp-1.1.0/src/livemcp/tools/__init__.py +1 -0
- livemcp-1.1.0/src/livemcp/tools/arrangement.py +135 -0
- livemcp-1.1.0/src/livemcp/tools/clips.py +858 -0
- livemcp-1.1.0/src/livemcp/tools/devices.py +402 -0
- livemcp-1.1.0/src/livemcp/tools/grooves.py +89 -0
- livemcp-1.1.0/src/livemcp/tools/mixer.py +200 -0
- livemcp-1.1.0/src/livemcp/tools/session.py +589 -0
- livemcp-1.1.0/src/livemcp/tools/tracks.py +425 -0
- livemcp-1.1.0/uv.lock +826 -0
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# LiveMCP Claude Skills
|
|
2
|
+
|
|
3
|
+
Project-specific skills for Ableton Live MCP development.
|
|
4
|
+
|
|
5
|
+
| Skill | When to use |
|
|
6
|
+
|-------|-------------|
|
|
7
|
+
| `/verify` | Before every commit — tests, tool count check |
|
|
8
|
+
| `/restart-ableton` | After modifying remote script files |
|
|
9
|
+
| `/publish` | Publish new version to PyPI |
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# /publish — Publish to PyPI
|
|
2
|
+
|
|
3
|
+
Release a new version of livemcp.
|
|
4
|
+
|
|
5
|
+
## Pre-flight
|
|
6
|
+
|
|
7
|
+
1. Run `/verify` first
|
|
8
|
+
2. Test with Ableton Live (run `/restart-ableton` + verify all 171 tools work)
|
|
9
|
+
3. Update version in `pyproject.toml`
|
|
10
|
+
4. Update CHANGELOG or README with new features/fixes
|
|
11
|
+
5. Commit: `git commit -m "Bump version to X.Y.Z"`
|
|
12
|
+
6. Tag: `git tag vX.Y.Z`
|
|
13
|
+
7. Push: `git push && git push --tags`
|
|
14
|
+
|
|
15
|
+
## Build and Publish
|
|
16
|
+
|
|
17
|
+
```bash
|
|
18
|
+
# Clean previous builds
|
|
19
|
+
rm -rf dist/
|
|
20
|
+
|
|
21
|
+
# Build package
|
|
22
|
+
uv build
|
|
23
|
+
|
|
24
|
+
# Check package contents
|
|
25
|
+
tar tzf dist/livemcp-*.tar.gz
|
|
26
|
+
|
|
27
|
+
# Publish to PyPI (requires API token)
|
|
28
|
+
uv publish
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
## Verify Publication
|
|
32
|
+
|
|
33
|
+
```bash
|
|
34
|
+
# Install from PyPI
|
|
35
|
+
uvx livemcp@X.Y.Z
|
|
36
|
+
|
|
37
|
+
# Should connect to Ableton on port 9877
|
|
38
|
+
# Test with Claude Desktop or Claude Code
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
## Rollback
|
|
42
|
+
|
|
43
|
+
PyPI doesn't allow deleting versions. If bad release:
|
|
44
|
+
1. Publish a new patch version (X.Y.Z+1)
|
|
45
|
+
2. Update docs/README to skip the broken version
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# /restart-ableton — Restart Ableton Live
|
|
2
|
+
|
|
3
|
+
Critical procedure after modifying remote script files. Clears Python bytecode cache so Ableton loads fresh code.
|
|
4
|
+
|
|
5
|
+
## Quick Version
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
bash scripts/restart_ableton.sh
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Manual Steps (if script fails)
|
|
12
|
+
|
|
13
|
+
```bash
|
|
14
|
+
# 1. Clear bytecode cache
|
|
15
|
+
find /home/alaarab/Sites/livemcp/remote_script -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
|
|
16
|
+
|
|
17
|
+
# 2. Quit Ableton
|
|
18
|
+
osascript -e 'tell application "Ableton Live 12 Suite" to quit'
|
|
19
|
+
sleep 2
|
|
20
|
+
|
|
21
|
+
# 3. Dismiss save dialog
|
|
22
|
+
osascript -e 'tell application "System Events" to tell process "Ableton Live 12 Suite" to if exists window 1 then click button "Don'\''t Save" of window 1' 2>/dev/null
|
|
23
|
+
|
|
24
|
+
# 4. Wait for exit (max 15s)
|
|
25
|
+
for i in $(seq 1 15); do
|
|
26
|
+
pgrep -x "Ableton Live" > /dev/null 2>&1 || break
|
|
27
|
+
sleep 1
|
|
28
|
+
done
|
|
29
|
+
|
|
30
|
+
# 5. Force kill if hanging
|
|
31
|
+
pgrep -x "Ableton Live" > /dev/null 2>&1 && pkill -9 -x "Ableton Live" && sleep 2
|
|
32
|
+
|
|
33
|
+
# 6. Relaunch
|
|
34
|
+
open -a "Ableton Live 12 Suite"
|
|
35
|
+
|
|
36
|
+
# 7. Dismiss "unexpectedly quit" dialog (poll for 10s)
|
|
37
|
+
for i in $(seq 1 10); do
|
|
38
|
+
osascript -e 'tell application "System Events" to tell process "Ableton Live 12 Suite" to if exists window 1 then click button "Reopen" of window 1' 2>/dev/null && break
|
|
39
|
+
sleep 1
|
|
40
|
+
done
|
|
41
|
+
|
|
42
|
+
# 8. Wait for LiveMCP socket (port 9877)
|
|
43
|
+
for i in $(seq 1 30); do
|
|
44
|
+
python3 -c "import socket; s=socket.socket(); s.settimeout(2); s.connect(('127.0.0.1', 9877)); s.close()" 2>/dev/null && break
|
|
45
|
+
sleep 3
|
|
46
|
+
done
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Verify
|
|
50
|
+
|
|
51
|
+
1. Check Ableton status bar: "LiveMCP: Server started on port 9877"
|
|
52
|
+
2. Test MCP server: `uvx livemcp` (should connect)
|
|
53
|
+
|
|
54
|
+
## Common Issues
|
|
55
|
+
|
|
56
|
+
- **Cache not cleared**: Ableton loads old .pyc files → always clear `__pycache__` first
|
|
57
|
+
- **Save dialog blocks**: Script clicks "Don't Save" automatically
|
|
58
|
+
- **Socket timeout**: Takes 15-30s for port 9877 to be ready after launch
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
# /verify — Pre-Commit Gate
|
|
2
|
+
|
|
3
|
+
Run before `git commit`. Tests and tool registration check.
|
|
4
|
+
|
|
5
|
+
## Steps
|
|
6
|
+
|
|
7
|
+
### 1. Tool Count
|
|
8
|
+
```bash
|
|
9
|
+
uv run python -c "from livemcp.server import mcp; print(f'{len(mcp._tool_manager._tools)} tools registered')"
|
|
10
|
+
```
|
|
11
|
+
✅ 171 tools | ❌ If count is wrong, check server.py registrations
|
|
12
|
+
|
|
13
|
+
### 2. Syntax Check (all Python files)
|
|
14
|
+
```bash
|
|
15
|
+
find . -name "*.py" -not -path "./.venv/*" | xargs -I{} python3 -c "import py_compile; py_compile.compile('{}', doraise=True)"
|
|
16
|
+
```
|
|
17
|
+
✅ All files valid | ❌ Report syntax errors
|
|
18
|
+
|
|
19
|
+
### 3. Lint (Ruff)
|
|
20
|
+
```bash
|
|
21
|
+
uv run ruff check src/livemcp/
|
|
22
|
+
```
|
|
23
|
+
✅ Clean | ❌ Fix with `uv run ruff check --fix src/livemcp/`
|
|
24
|
+
|
|
25
|
+
### 4. Git Status
|
|
26
|
+
```bash
|
|
27
|
+
git status
|
|
28
|
+
```
|
|
29
|
+
✅ No `.env` or credentials in staging
|
|
30
|
+
|
|
31
|
+
### 4. Remote Script Check
|
|
32
|
+
```bash
|
|
33
|
+
ls -l ~/Music/"Ableton/User Library/Remote Scripts/LiveMCP/" | grep __init__
|
|
34
|
+
```
|
|
35
|
+
✅ Symlink intact | ⚠️ If broken, run `./scripts/install.sh`
|
|
36
|
+
|
|
37
|
+
## Output
|
|
38
|
+
|
|
39
|
+
```
|
|
40
|
+
/verify Report
|
|
41
|
+
|
|
42
|
+
1. Tools ✅ 171 tools registered
|
|
43
|
+
2. Syntax ✅ All Python files valid
|
|
44
|
+
3. Lint ✅ Ruff clean
|
|
45
|
+
4. Git status ✅ Clean
|
|
46
|
+
5. Remote script ✅ Symlink intact
|
|
47
|
+
|
|
48
|
+
RESULT: ✅ SAFE TO COMMIT
|
|
49
|
+
```
|
livemcp-1.1.0/.gitignore
ADDED
livemcp-1.1.0/CLAUDE.md
ADDED
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
# LiveMCP — Claude Code Instructions
|
|
2
|
+
|
|
3
|
+
## Project Overview
|
|
4
|
+
|
|
5
|
+
LiveMCP is a Model Context Protocol (MCP) bridge that exposes Ableton Live's internal Python API to AI assistants. Version 1.0.0, published on PyPI as `livemcp`, invoked via `uvx livemcp`.
|
|
6
|
+
|
|
7
|
+
It provides 171 tools across 7 categories: session, clips, tracks, devices, mixer, arrangement, grooves.
|
|
8
|
+
|
|
9
|
+
macOS only. The remote script relies on Ableton's macOS application bundle structure and the osascript-based install/restart scripts target macOS paths exclusively.
|
|
10
|
+
|
|
11
|
+
## Architecture
|
|
12
|
+
|
|
13
|
+
LiveMCP has two components that must stay in sync:
|
|
14
|
+
|
|
15
|
+
**MCP Server (`src/livemcp/`)** — Python 3.10+, FastMCP, communicates with Ableton over a TCP socket.
|
|
16
|
+
|
|
17
|
+
- `src/livemcp/server.py` — FastMCP instance, registers all tools
|
|
18
|
+
- `src/livemcp/connection.py` — singleton TCP connection to Ableton
|
|
19
|
+
- `src/livemcp/tools/` — one module per category, each exports a `TOOLS` list of functions
|
|
20
|
+
|
|
21
|
+
**Remote Script (`remote_script/LiveMCP/`)** — Runs inside Ableton Live's embedded Python 3.11 interpreter as a MIDI Remote Script (extends `ControlSurface`).
|
|
22
|
+
|
|
23
|
+
- `remote_script/LiveMCP/server.py` — TCP server, command dispatcher
|
|
24
|
+
- `remote_script/LiveMCP/handlers/` — one module per category, each exports `READ_HANDLERS` and `WRITE_HANDLERS` dicts
|
|
25
|
+
|
|
26
|
+
## Connection Details
|
|
27
|
+
|
|
28
|
+
- Host: `127.0.0.1`, Port: `9877`
|
|
29
|
+
- Singleton: one `AbletonConnection` instance shared across all tool calls (thread-safe via `threading.Lock`)
|
|
30
|
+
- Timeout: 15 seconds per command
|
|
31
|
+
- Retries: 3 attempts with 1-second delay between attempts
|
|
32
|
+
- Validation: on first connect, `get_session_info` is sent as a ping to confirm the remote script is ready
|
|
33
|
+
|
|
34
|
+
## READ vs WRITE Handler Threading Model
|
|
35
|
+
|
|
36
|
+
This is the most important rule when adding handlers in `remote_script/LiveMCP/handlers/`:
|
|
37
|
+
|
|
38
|
+
- **READ_HANDLERS** run directly on the socket thread. Safe for reading Live object properties.
|
|
39
|
+
- **WRITE_HANDLERS** are dispatched to Ableton's main thread via `schedule_message`. Required for any mutation of Live's object model (setting properties, calling methods that modify state).
|
|
40
|
+
|
|
41
|
+
**Putting a write operation in READ_HANDLERS will crash or corrupt Ableton's state.** When in doubt, use WRITE_HANDLERS.
|
|
42
|
+
|
|
43
|
+
## Adding a New Tool
|
|
44
|
+
|
|
45
|
+
Adding a tool requires changes in four places:
|
|
46
|
+
|
|
47
|
+
**Step 1 — Add the tool function** in `src/livemcp/tools/<category>.py`:
|
|
48
|
+
|
|
49
|
+
```python
|
|
50
|
+
def my_new_tool(track_index: int, value: float) -> str:
|
|
51
|
+
"""One-line summary for the AI assistant.
|
|
52
|
+
|
|
53
|
+
Args:
|
|
54
|
+
track_index: Zero-based track index.
|
|
55
|
+
value: The value to set.
|
|
56
|
+
"""
|
|
57
|
+
result = get_connection().send_command("my_new_tool", {
|
|
58
|
+
"track_index": track_index,
|
|
59
|
+
"value": value,
|
|
60
|
+
})
|
|
61
|
+
return json.dumps(result)
|
|
62
|
+
```
|
|
63
|
+
|
|
64
|
+
**Step 2 — Append to TOOLS list** at the bottom of the same file:
|
|
65
|
+
|
|
66
|
+
```python
|
|
67
|
+
TOOLS = [
|
|
68
|
+
# ... existing tools ...
|
|
69
|
+
my_new_tool,
|
|
70
|
+
]
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
**Step 3 — Add the handler** in `remote_script/LiveMCP/handlers/<category>.py`:
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
def my_new_tool(control_surface, params):
|
|
77
|
+
track_index = params.get("track_index")
|
|
78
|
+
value = params.get("value")
|
|
79
|
+
if track_index is None or value is None:
|
|
80
|
+
raise ValueError("Missing required parameters")
|
|
81
|
+
song = control_surface.song()
|
|
82
|
+
track = song.tracks[track_index]
|
|
83
|
+
# mutate state here
|
|
84
|
+
return {"ok": True}
|
|
85
|
+
```
|
|
86
|
+
|
|
87
|
+
**Step 4 — Register in READ_HANDLERS or WRITE_HANDLERS** in the same handler file:
|
|
88
|
+
|
|
89
|
+
```python
|
|
90
|
+
READ_HANDLERS = {
|
|
91
|
+
# read-only: runs on socket thread
|
|
92
|
+
"get_something": get_something,
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
WRITE_HANDLERS = {
|
|
96
|
+
# state mutation: queued to Ableton's main thread
|
|
97
|
+
"my_new_tool": my_new_tool,
|
|
98
|
+
}
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
The command string (e.g. `"my_new_tool"`) must be identical in `send_command(...)` and the handler dict key.
|
|
102
|
+
|
|
103
|
+
## Project Structure
|
|
104
|
+
|
|
105
|
+
```
|
|
106
|
+
src/livemcp/
|
|
107
|
+
server.py # FastMCP instance, registers all tools from TOOLS lists
|
|
108
|
+
connection.py # AbletonConnection singleton, send_command()
|
|
109
|
+
tools/
|
|
110
|
+
session.py # tempo, transport, time signature, cue points
|
|
111
|
+
tracks.py # create/delete/rename tracks, arm, solo, mute
|
|
112
|
+
clips.py # create clips, add notes, quantize, warp
|
|
113
|
+
devices.py # load instruments/effects, device parameters
|
|
114
|
+
mixer.py # volume, pan, send levels, routing
|
|
115
|
+
arrangement.py # arrangement view clips
|
|
116
|
+
grooves.py # groove pool
|
|
117
|
+
|
|
118
|
+
remote_script/LiveMCP/
|
|
119
|
+
__init__.py # ControlSurface entry point
|
|
120
|
+
server.py # TCP server + dispatcher (READ vs WRITE routing)
|
|
121
|
+
handlers/
|
|
122
|
+
__init__.py # aggregates all READ/WRITE handler dicts
|
|
123
|
+
session.py
|
|
124
|
+
tracks.py
|
|
125
|
+
clips.py
|
|
126
|
+
devices.py
|
|
127
|
+
mixer.py
|
|
128
|
+
arrangement.py
|
|
129
|
+
grooves.py
|
|
130
|
+
|
|
131
|
+
scripts/
|
|
132
|
+
install.sh # symlinks remote_script/LiveMCP into Ableton's MIDI Remote Scripts dir
|
|
133
|
+
uninstall.sh # removes the symlink from all detected Ableton versions
|
|
134
|
+
restart_ableton.sh # full restart procedure (cache clear, quit, relaunch, wait for socket)
|
|
135
|
+
```
|
|
136
|
+
|
|
137
|
+
## Restarting Ableton Live
|
|
138
|
+
|
|
139
|
+
When you need to restart Ableton (e.g. after modifying remote script files), **always** use this procedure:
|
|
140
|
+
|
|
141
|
+
```bash
|
|
142
|
+
# 1. Clear bytecode cache so Ableton loads fresh Python
|
|
143
|
+
find /home/alaarab/Sites/livemcp/remote_script -name "__pycache__" -type d -exec rm -rf {} + 2>/dev/null
|
|
144
|
+
|
|
145
|
+
# 2. Gracefully quit (sends save dialog — dismiss it)
|
|
146
|
+
osascript -e 'tell application "Ableton Live 12 Suite" to quit'
|
|
147
|
+
|
|
148
|
+
# 3. Dismiss any "Save" dialog that appears
|
|
149
|
+
sleep 2
|
|
150
|
+
osascript -e 'tell application "System Events" to tell process "Ableton Live 12 Suite" to if exists window 1 then click button "Don'\''t Save" of window 1' 2>/dev/null
|
|
151
|
+
|
|
152
|
+
# 4. Wait for process to fully exit
|
|
153
|
+
for i in $(seq 1 15); do
|
|
154
|
+
pgrep -x "Ableton Live" > /dev/null 2>&1 || break
|
|
155
|
+
sleep 1
|
|
156
|
+
done
|
|
157
|
+
|
|
158
|
+
# 5. Force kill if it's still hanging
|
|
159
|
+
pgrep -x "Ableton Live" > /dev/null 2>&1 && pkill -9 -x "Ableton Live" && sleep 2
|
|
160
|
+
|
|
161
|
+
# 6. Relaunch
|
|
162
|
+
open -a "Ableton Live 12 Suite"
|
|
163
|
+
|
|
164
|
+
# 7. Dismiss "unexpectedly quit" dialog if it appears (poll for a few seconds)
|
|
165
|
+
for i in $(seq 1 10); do
|
|
166
|
+
osascript -e 'tell application "System Events" to tell process "Ableton Live 12 Suite" to if exists window 1 then click button "Reopen" of window 1' 2>/dev/null && break
|
|
167
|
+
sleep 1
|
|
168
|
+
done
|
|
169
|
+
|
|
170
|
+
# 8. Wait for LiveMCP socket to be ready
|
|
171
|
+
for i in $(seq 1 30); do
|
|
172
|
+
python3 -c "import socket; s=socket.socket(); s.settimeout(2); s.connect(('127.0.0.1', 9877)); s.close()" 2>/dev/null && break
|
|
173
|
+
sleep 3
|
|
174
|
+
done
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
Or use the helper script: `bash scripts/restart_ableton.sh`
|
|
178
|
+
|
|
179
|
+
### Important Notes
|
|
180
|
+
|
|
181
|
+
- **Always clear `__pycache__`** before restarting — Ableton caches .pyc files and won't see your changes otherwise
|
|
182
|
+
- The "unexpectedly quit" dialog appears if the previous quit wasn't clean. The script handles this automatically.
|
|
183
|
+
- The "Save?" dialog appears on graceful quit. The script clicks "Don't Save" — if you need to save, do it manually first.
|
|
184
|
+
- Socket on port 9877 typically takes 15-30 seconds after launch to become available.
|
|
185
|
+
|
|
186
|
+
## Verification After Changes
|
|
187
|
+
|
|
188
|
+
```bash
|
|
189
|
+
# Syntax check all Python files
|
|
190
|
+
find . -name "*.py" -not -path "./.venv/*" | xargs -I{} python3 -c "import py_compile; py_compile.compile('{}', doraise=True)"
|
|
191
|
+
|
|
192
|
+
# Verify registered tool count (target: 171)
|
|
193
|
+
uv run python -c "from livemcp.server import mcp; print(len(mcp._tool_manager._tools), 'tools')"
|
|
194
|
+
|
|
195
|
+
# Lint with ruff (line-length 100, configured in pyproject.toml)
|
|
196
|
+
uv run ruff check src/livemcp/
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
## Code Style
|
|
200
|
+
|
|
201
|
+
Ruff is the linter. Line length is 100, configured in `pyproject.toml` under `[tool.ruff]`. Run `uv run ruff check src/livemcp/` before committing. Run `uv run ruff format src/livemcp/` to auto-format.
|
|
202
|
+
|
|
203
|
+
## Known API Gotchas
|
|
204
|
+
|
|
205
|
+
- `MidiNoteSpecification`: must use constructor kwargs, NOT attribute setting
|
|
206
|
+
- `apply_note_modifications`: pass the original tuple from `get_notes_extended`, don't convert to list
|
|
207
|
+
- `quantize_clip` grid: must be int, not float
|
|
208
|
+
- Mixer zero-value: never use `params.get("x") or params.get("y")` — use explicit None checks (0.0 is falsy)
|
|
209
|
+
- `scene.tempo`: can't set to -1.0 to clear; use `scene.tempo_enabled = False` instead
|
|
210
|
+
- `clip.groove = None` doesn't work; groove removal is an API limitation
|
livemcp-1.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Ala Arab
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|