408 lines
14 KiB
Markdown
408 lines
14 KiB
Markdown
# DOCUMENTO TÉCNICO PARA CODEX
|
|
## Implementación de Handlers Runtime - AbletonMCP-AI
|
|
|
|
**Fecha:** 2026-04-07
|
|
**Autor:** OpenCode (Kimi K2.5)
|
|
**Destinatario:** Codex
|
|
**Prioridad:** P0 - Crítico
|
|
**Estado:** Sistema NO funcional para producción musical real
|
|
|
|
---
|
|
|
|
## 1. RESUMEN EJECUTIVO
|
|
|
|
El sistema MCP tiene **220+ herramientas registradas** en `server.py` pero **menos del 30% tienen handlers funcionales** en `abletonmcp_init.py`.
|
|
|
|
**El resultado:** La API reporta éxito pero Ableton Live NO realiza las operaciones. Los clips son "phantom" - existen en la API pero no producen sonido.
|
|
|
|
---
|
|
|
|
## 2. ARQUITECTURA DE 3 LAYERS
|
|
|
|
```
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ LAYER 1: MCP Transport & Public Tools (server.py) │
|
|
│ ├── 220+ herramientas MCP registradas ✅ │
|
|
│ └── Todas retornan JSON con "status": "success" │
|
|
└──────────────────────┬──────────────────────────────────────┘
|
|
│ Socket (port 9877)
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ LAYER 2: Socket Protocol / Runtime Bridge │
|
|
│ ├── abletonmcp_runtime.py (shim) │
|
|
│ └── Envía comandos vía socket │
|
|
└──────────────────────┬──────────────────────────────────────┘
|
|
│
|
|
▼
|
|
┌─────────────────────────────────────────────────────────────┐
|
|
│ LAYER 3: Ableton Remote Script / Live API │
|
|
│ ├── abletonmcp_init.py (handlers de comandos) │
|
|
│ └── SOLO ~60 handlers implementados de 220+ necesarios ❌ │
|
|
└─────────────────────────────────────────────────────────────┘
|
|
```
|
|
|
|
**Problema:** El Layer 1 reporta éxito porque el Layer 3 retorna `{"status": "ok"}` pero muchos handlers están vacíos o no ejecutan la acción real en Live.
|
|
|
|
---
|
|
|
|
## 3. CATEGORÍAS DE HERRAMIENTAS ROTA
|
|
|
|
### 3.1 FX & Dynamics (T040-T050) - CRÍTICO
|
|
|
|
| Herramienta | MCP Tool | Handler en init.py | Estado |
|
|
|-------------|----------|-------------------|--------|
|
|
| `apply_sidechain_pump` | ✅ Registrada | ❌ `setup_sidechain` NO EXISTE | **ROTO** |
|
|
| `write_volume_automation` | ✅ Registrada | ❌ `write_track_automation` NO EXISTE | **ROTO** |
|
|
| `apply_clip_fades` | ✅ Registrada | ⚠️ Parcial - usa `write_clip_envelope` (no testeado) | **DUDOSO** |
|
|
| `inject_pattern_fills` | ✅ Registrada | ❌ `inject_fills` NO EXISTE | **ROTO** |
|
|
| `humanize_set` | ✅ Registrada | ⚠️ No aplica cambios reales a Live | **ROTO** |
|
|
|
|
**Error típico:**
|
|
```json
|
|
{
|
|
"status": "success",
|
|
"action": "apply_sidechain_pump",
|
|
"result": {
|
|
"status": "error",
|
|
"message": "Unknown command: setup_sidechain"
|
|
}
|
|
}
|
|
```
|
|
|
|
### 3.2 Arrangement Intelligence (T086-T094) - CRÍTICO
|
|
|
|
| Herramienta | MCP Tool | Handler | Estado |
|
|
|-------------|----------|---------|--------|
|
|
| `create_arrangement_clip` | ✅ | ⚠️ `_create_arrangement_clip` existe pero crea clips vacíos | **ROTO** |
|
|
| `add_notes_to_arrangement_clip` | ✅ | ✅ Funciona | **OK** |
|
|
| `duplicate_clip_to_arrangement` | ✅ | ⚠️ Funciona parcialmente | **PARCIAL** |
|
|
| `apply_groove_to_section` | ✅ | ❌ NO EXISTE | **ROTO** |
|
|
| `create_arrangement_audio_pattern` | ✅ | ❌ `_create_arrangement_audio_pattern` FALLA | **ROTO** |
|
|
|
|
**Problema específico:** `create_arrangement_audio_pattern` reporta clips creados pero Ableton NO los materializa (phantom clips).
|
|
|
|
### 3.3 Sample Loading & Audio (T015-T035) - CRÍTICO
|
|
|
|
| Herramienta | MCP Tool | Handler | Estado |
|
|
|-------------|----------|---------|--------|
|
|
| `select_samples_for_genre` | ✅ | N/A (selector lógico) | **OK** |
|
|
| `load_sample_to_track` | ❌ NO REGISTRADA | ❌ NO EXISTE | **FALTANTE** |
|
|
| `create_drum_pattern` | ✅ | ✅ Crea clips MIDI vacíos | **PARCIAL** |
|
|
| `get_sample_pack_for_project` | ✅ | N/A (selector lógico) | **OK** |
|
|
|
|
**Problema:** No hay forma de cargar samples de `librerias\organized_samples\` en Drum Racks o Simpler.
|
|
|
|
### 3.4 Harmonic Engine (T051-T062) - FUNCIONAL
|
|
|
|
| Herramienta | Estado |
|
|
|-------------|--------|
|
|
| `analyze_key_compatibility` | ✅ OK (Python puro) |
|
|
| `suggest_key_change` | ✅ OK (Python puro) |
|
|
| `validate_sample_key` | ✅ OK (Python puro) |
|
|
|
|
**Nota:** Estas funcionan porque no interactúan con Live API.
|
|
|
|
### 3.5 Hardware Integration (T166-T180) - NO IMPLEMENTADO
|
|
|
|
| Herramienta | Estado |
|
|
|-------------|--------|
|
|
| `ableton_mcp_ai_get_hardware_mapping` | ❌ Handler vacío |
|
|
| `ableton_mcp_ai_bind_filter_to_bus` | ❌ Handler vacío |
|
|
| `ableton_mcp_ai_trigger_scene_hardware` | ❌ Handler vacío |
|
|
|
|
---
|
|
|
|
## 4. HANDLERS ESPECÍFICOS QUE FALTAN EN abletonmcp_init.py
|
|
|
|
### 4.1 Comandos NO Registrados en `_process_command()`
|
|
|
|
Agregar en la sección de comandos (aprox línea 340):
|
|
|
|
```python
|
|
# FX & Dynamics - FALTANTES
|
|
"setup_sidechain", # T045
|
|
"write_track_automation", # T042
|
|
"write_reverb_automation", # T073
|
|
"write_filter_automation", # T072
|
|
"inject_fills", # T048
|
|
"apply_groove", # T077
|
|
|
|
# Arrangement - FALTANTES
|
|
"apply_groove_to_section", # T086
|
|
"set_loop_markers", # T067
|
|
"apply_filter_sweep", # T072
|
|
"apply_reverb_tail", # T073
|
|
"apply_pitch_riser", # T074
|
|
"apply_micro_timing", # T075
|
|
|
|
# Sample Loading - FALTANTES
|
|
"load_sample_to_track", # NUEVO
|
|
"load_sample_to_drum_rack", # NUEVO
|
|
"replace_clip_sample", # NUEVO
|
|
|
|
# Mastering - FALTANTES
|
|
"calibrate_gain_staging", # T079
|
|
"run_mix_quality_check", # T085
|
|
```
|
|
|
|
### 4.2 Handlers Que Necesitan Implementación
|
|
|
|
#### A. `setup_sidechain` (T045)
|
|
|
|
**Ubicación:** Agregar después de `_set_device_parameter` (~línea 2900)
|
|
|
|
**Funcionalidad requerida:**
|
|
```python
|
|
def _setup_sidechain(self, target_track, source_track, compressor_params, style):
|
|
"""
|
|
Configura sidechain compressor en target_track usando source_track como input.
|
|
|
|
Pasos:
|
|
1. Cargar Compressor en target_track si no existe
|
|
2. Activar Sidechain en Compressor
|
|
3. Setear source_track como input
|
|
4. Aplicar compressor_params (threshold, ratio, attack, release)
|
|
"""
|
|
```
|
|
|
|
**Parámetros típicos:**
|
|
- `threshold`: -20 a -10 dB
|
|
- `ratio`: 2:1 a 8:1
|
|
- `attack`: 0.1 a 10 ms
|
|
- `release`: 50 a 300 ms
|
|
|
|
#### B. `write_track_automation` (T042)
|
|
|
|
**Funcionalidad requerida:**
|
|
```python
|
|
def _write_track_automation(self, track_index, parameter, points, track_type="track"):
|
|
"""
|
|
Escribe automatización de volumen/pan/device en un track.
|
|
|
|
Pasos:
|
|
1. Seleccionar parámetro para automatización
|
|
2. Crear puntos de automatización en los tiempos especificados
|
|
3. Aplicar valores (interpolando entre puntos)
|
|
"""
|
|
```
|
|
|
|
**Ejemplo de uso:**
|
|
```json
|
|
{
|
|
"track_index": 11,
|
|
"parameter": "volume",
|
|
"points": [
|
|
{"time": 0, "value": 0.0},
|
|
{"time": 32, "value": 0.85},
|
|
{"time": 64, "value": 0.0}
|
|
]
|
|
}
|
|
```
|
|
|
|
#### C. `load_sample_to_drum_rack` (NUEVO - CRÍTICO)
|
|
|
|
**Este es el handler más importante que falta.**
|
|
|
|
```python
|
|
def _load_sample_to_drum_rack(self, track_index, sample_path, pad_note, drum_rack_index=0):
|
|
"""
|
|
Carga un sample de audio en un Drum Rack.
|
|
|
|
Pasos:
|
|
1. Verificar que track tiene Drum Rack
|
|
2. Cargar sample_path en el pad correspondiente a pad_note
|
|
3. Configurar parámetros básicos (gain, env, etc)
|
|
|
|
Args:
|
|
track_index: Índice del track con Drum Rack
|
|
sample_path: Ruta absoluta al sample (WAV/AIFF)
|
|
pad_note: Nota MIDI del pad (36=C1=kick, 38=D1=snare, etc)
|
|
drum_rack_index: Índice del Drum Rack en el track
|
|
"""
|
|
```
|
|
|
|
**Ejemplo real:**
|
|
```python
|
|
# Cargar kick en track 1 (KICK)
|
|
self._load_sample_to_drum_rack(
|
|
track_index=1,
|
|
sample_path="C:\\...\\librerias\\organized_samples\\textures\\kick\\Kit_01_Kick_A#_125.wav",
|
|
pad_note=36 # C1 = kick
|
|
)
|
|
```
|
|
|
|
#### D. `inject_fills` (T048)
|
|
|
|
**Funcionalidad requerida:**
|
|
```python
|
|
def _inject_fills(self, track_index, fill_type, positions, section):
|
|
"""
|
|
Inyecta fills de batería (snare rolls, flams, etc) en posiciones específicas.
|
|
|
|
Pasos:
|
|
1. Para cada posición en positions:
|
|
- Crear clip temporal o usar clip existente
|
|
- Añadir notas de fill (roll de snare, tom fill, etc)
|
|
"""
|
|
```
|
|
|
|
---
|
|
|
|
## 5. PROBLEMAS ESPECÍFICOS EN create_arrangement_audio_pattern
|
|
|
|
**Ubicación:** `abletonmcp_init.py` línea ~1233
|
|
|
|
**Código actual (ROTO):**
|
|
```python
|
|
def _create_arrangement_audio_pattern(self, track_index, file_path, positions, name=""):
|
|
try:
|
|
track = self._song.tracks[track_index]
|
|
created_clips = []
|
|
|
|
for position in positions:
|
|
clip_slot = track.clip_slots[0] # USAR SLOT 0 - PROBLEMA
|
|
if hasattr(clip_slot, 'create_audio_clip'):
|
|
clip = clip_slot.create_audio_clip(file_path) # MÉTODO DUDOSO
|
|
# ... resto del código
|
|
```
|
|
|
|
**Problemas:**
|
|
1. Usa `clip_slots[0]` en lugar de crear clip en Arrangement directamente
|
|
2. `create_audio_clip` puede no existir en la API de Live 12
|
|
3. No verifica que el archivo existe antes de crear
|
|
4. No maneja errores de formato de audio
|
|
|
|
**Solución propuesta:**
|
|
```python
|
|
def _create_arrangement_audio_pattern(self, track_index, file_path, positions, name=""):
|
|
"""
|
|
Crea clips de audio en Arrangement View con samples reales.
|
|
"""
|
|
import os
|
|
|
|
# 1. Verificar archivo existe
|
|
if not os.path.exists(file_path):
|
|
raise FileNotFoundError(f"Sample no encontrado: {file_path}")
|
|
|
|
track = self._song.tracks[track_index]
|
|
created_clips = []
|
|
|
|
for position in positions:
|
|
start_time = float(position)
|
|
|
|
# 2. Crear clip de audio en Arrangement (NO en Session)
|
|
# Método A: Usar track.create_audio_clip si existe
|
|
if hasattr(track, 'create_audio_clip'):
|
|
clip = track.create_audio_clip(start_time)
|
|
# Método B: Usar song.duplicate_clip_to_arrangement
|
|
elif hasattr(self._song, 'duplicate_clip_to_arrangement'):
|
|
# Crear clip temporal en Session, luego duplicar a Arrangement
|
|
temp_slot = track.clip_slots[0]
|
|
if temp_slot.has_clip:
|
|
temp_slot.delete_clip()
|
|
# ... lógica de carga de sample ...
|
|
|
|
# 3. Asignar sample al clip
|
|
if clip and hasattr(clip, 'file_path'):
|
|
clip.file_path = file_path
|
|
|
|
created_clips.append({
|
|
"start_time": start_time,
|
|
"file_path": file_path,
|
|
"name": name or os.path.basename(file_path)
|
|
})
|
|
|
|
return {"clips_created": len(created_clips), "clips": created_clips}
|
|
```
|
|
|
|
---
|
|
|
|
## 6. PRIORIDADES DE IMPLEMENTACIÓN
|
|
|
|
### P0 - CRÍTICO (Sistema no funciona sin esto)
|
|
|
|
1. **`load_sample_to_drum_rack`** - Sin esto, no hay sonido real
|
|
2. **`setup_sidechain`** - Sidechain es esencial para mezcla profesional
|
|
3. **Fix `create_arrangement_audio_pattern`** - Para que los clips de audio realmente carguen samples
|
|
|
|
### P1 - ALTO (Mejora calidad dramáticamente)
|
|
|
|
4. **`write_track_automation`** - Para fades, builds, automatización
|
|
5. **`inject_fills`** - Para variación rítmica profesional
|
|
6. **`apply_groove_to_section`** - Para humanización de timing
|
|
7. **`calibrate_gain_staging`** - Para mezcla con niveles correctos
|
|
|
|
### P2 - MEDIO (Features avanzadas)
|
|
|
|
8. Hardware integration handlers (T166-T180)
|
|
9. Advanced FX chains
|
|
10. Spectral quality analysis integration
|
|
|
|
---
|
|
|
|
## 7. VERIFICACIÓN POST-IMPLEMENTACIÓN
|
|
|
|
### Tests de validación que deben pasar:
|
|
|
|
```python
|
|
# Test 1: Sample Loading
|
|
def test_sample_loading():
|
|
result = ableton.send_command("load_sample_to_drum_rack", {
|
|
"track_index": 1,
|
|
"sample_path": ".../kick.wav",
|
|
"pad_note": 36
|
|
})
|
|
assert result["status"] == "success"
|
|
# Verificar: El clip debe producir sonido al reproducir
|
|
|
|
# Test 2: Sidechain
|
|
def test_sidechain():
|
|
result = ableton.send_command("setup_sidechain", {
|
|
"target_track": 11, # bass
|
|
"source_track": 1, # kick
|
|
"compressor_params": {"threshold": -20, "ratio": 4, "attack": 5, "release": 100}
|
|
})
|
|
assert result["status"] == "success"
|
|
# Verificar: Compressor aparece en el track con sidechain activado
|
|
|
|
# Test 3: Audio Pattern Real
|
|
def test_audio_pattern_real():
|
|
result = ableton.send_command("create_arrangement_audio_pattern", {
|
|
"track_index": 5,
|
|
"file_path": ".../loop.wav",
|
|
"positions": [0, 16, 32]
|
|
})
|
|
assert result["status"] == "success"
|
|
# Verificar: Los clips se ven en Arrangement y suenan
|
|
```
|
|
|
|
---
|
|
|
|
## 8. ARCHIVOS QUE NECESITAN MODIFICACIÓN
|
|
|
|
| Archivo | Líneas aprox | Cambios |
|
|
|---------|--------------|---------|
|
|
| `abletonmcp_init.py` | ~4000 | Agregar 10+ handlers nuevos |
|
|
| `server.py` | ~13700 | Verificar que tools llaman comandos correctos |
|
|
| `song_generator.py` | ~14500 | Integrar sample loading en generación |
|
|
|
|
---
|
|
|
|
## 9. CONCLUSIÓN
|
|
|
|
**El sistema actual es un prototipo funcional que genera estructura MIDI pero NO produce audio profesional.**
|
|
|
|
**Para hacerlo funcional necesita:**
|
|
1. Implementar handlers de sample loading
|
|
2. Arreglar audio pattern creation
|
|
3. Agregar sidechain y automatización real
|
|
4. Integrar las 827 samples de la librería
|
|
|
|
**Estimación de trabajo:** 2-3 días de implementación + 1 día de testing.
|
|
|
|
---
|
|
|
|
**Contacto:** Si tienes dudas sobre algún handler específico, revisa los docs de sprints anteriores en `docs/SPRINT_v0.1.*_NEXT_*.md` para contexto.
|
|
|
|
**Prioridad absoluta:** `load_sample_to_drum_rack` - sin esto el sistema no produce sonido real.
|