@mcptoolshop/pianoai 1.3.0 → 1.3.1

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.

Potentially problematic release.


This version of @mcptoolshop/pianoai might be problematic. Click here for more details.

package/README.es.md CHANGED
@@ -9,39 +9,35 @@
9
9
  <h1 align="center">PianoAI</h1>
10
10
 
11
11
  <p align="center">
12
- Servidor MCP + CLI para enseñanza de piano con IA reproduce a través de VMPK vía MIDI con retroalimentación por voz.
12
+ Reproductor de piano con motor de audio integradosuena por los altavoces, sin software externo necesario. Servidor MCP + CLI.
13
13
  </p>
14
14
 
15
- [![Tests](https://img.shields.io/badge/tests-181_passing-brightgreen)](https://github.com/mcp-tool-shop-org/pianoai)
16
- [![Smoke](https://img.shields.io/badge/smoke-29_passing-brightgreen)](https://github.com/mcp-tool-shop-org/pianoai)
17
- [![MCP Tools](https://img.shields.io/badge/MCP_tools-8-purple)](https://github.com/mcp-tool-shop-org/pianoai)
18
- [![Songs](https://img.shields.io/badge/songs-10_(via_ai--music--sheets)-blue)](https://github.com/mcp-tool-shop-org/ai-music-sheets)
15
+ [![Tests](https://img.shields.io/badge/tests-passing-brightgreen)](https://github.com/mcp-tool-shop-org/pianoai)
16
+ [![MCP Tools](https://img.shields.io/badge/MCP_tools-12-purple)](https://github.com/mcp-tool-shop-org/pianoai)
17
+ [![Songs](https://img.shields.io/badge/songs-10_built--in-blue)](https://github.com/mcp-tool-shop-org/ai-music-sheets)
19
18
 
20
19
  ## ¿Qué es esto?
21
20
 
22
- Un CLI en TypeScript y servidor MCP que carga canciones de piano desde [ai-music-sheets](https://github.com/mcp-tool-shop-org/ai-music-sheets), las convierte a MIDI y las reproduce a través de [VMPK](https://vmpk.sourceforge.io/) mediante un puerto MIDI virtual. El motor de enseñanza lanza interjecciones en los límites de compás y en momentos clave, permitiendo que un LLM actúe como profesor de piano en vivo con retroalimentación por voz y notificaciones aparte.
21
+ Un reproductor de piano en TypeScript que reproduce archivos MIDI estándar y canciones integradas a través de tus altavoces. No requiere software externo el motor de audio integrado se encarga de todo. Incluye un servidor MCP para integración con LLMs y un CLI para uso directo.
22
+
23
+ Soporta narración de canto en tiempo real y retroalimentación de enseñanza en vivo durante la reproducción.
23
24
 
24
25
  ## Características
25
26
 
27
+ - **Motor de piano integrado** — reproduce por los altavoces vía `node-web-audio-api`, sin hardware MIDI necesario
28
+ - **Soporte de archivos MIDI estándar** — reproduce cualquier archivo `.mid`: `pianoai play song.mid`
29
+ - **Canto en tiempo real** — narra nombres de notas, solfeo, contorno o sílabas durante la reproducción MIDI
30
+ - **Filtros de voz** — canta solo la melodía (nota más aguda), armonía (más grave) o todas las notas por acorde
31
+ - **Retroalimentación de enseñanza en vivo** — consejos de dinámica según la posición, avisos de rango, límites de sección, anuncios de hitos
32
+ - **Seguimiento de posición** — mapeo de pulso/compás/tempo desde MIDI en crudo con soporte de búsqueda
26
33
  - **4 modos de reproducción** — completa, compás por compás, manos separadas, bucle
27
- - **Control de velocidad** — práctica lenta a 0.5x hasta reproducción rápida a 2x, acumulable con modificación de tempo
28
- - **Seguimiento de progreso** — callbacks configurables en hitos porcentuales o por compás
29
- - **9 hooks de enseñanza** — console, silent, recording, callback, voice, aside, sing-along, compose, live feedback
30
- - **Narración de canto** — nombres de notas, solfeo, contorno o sílabas hablados antes de cada compás
31
- - **Canto sincronizado + piano** — concurrent (sensación de dúo) o before (voz primero) mediante `--with-piano`
32
- - **Retroalimentación por voz** — salida `VoiceDirective` para integración con mcp-voice-soundboard
33
- - **Retroalimentación en vivo** — estímulo en tiempo real, consejos de dinámica y avisos de dificultad durante la reproducción
34
- - **Interjecciones aparte** — salida `AsideDirective` para la bandeja de mcp-aside
34
+ - **Control de velocidad** — práctica lenta a 0.5x hasta 4x rápida, acumulable con modificación de tempo
35
+ - **Controles en tiempo real** — pausa, reanudación, cambio de velocidad, búsqueda durante la reproducción con listeners de eventos
36
+ - **12 herramientas MCP** — reproducir, pausar, velocidad, detener, explorar, cantar, enseñar todo mediante el protocolo MCP
37
+ - **12 hooks de enseñanza** — console, silent, recording, callback, voice, aside, sing-along, live feedback, MIDI singing, MIDI live feedback, compose
38
+ - **Salida MIDI opcional** — enrutar a software externo con la bandera `--midi` (requiere loopMIDI + VMPK)
35
39
  - **Análisis seguro** — las notas incorrectas se omiten con `ParseWarning`s recopilados
36
- - **8 herramientas MCP** — exponen el registro, notas de enseñanza, canto guiado y recomendaciones de canciones a LLMs
37
- - **Analizador de notas** — notación científica de altura a MIDI y viceversa
38
- - **Conector simulado** — cobertura completa de tests sin hardware MIDI
39
-
40
- ## Requisitos previos
41
-
42
- 1. **[loopMIDI](https://www.tobias-erichsen.de/software/loopmidi.html)** — crea un puerto MIDI virtual (ej. "loopMIDI Port")
43
- 2. **[VMPK](https://vmpk.sourceforge.io/)** — configura la entrada MIDI a tu puerto loopMIDI
44
- 3. **Node.js 18+**
40
+ - **Conector simulado** — cobertura completa de tests sin hardware
45
41
 
46
42
  ## Instalación
47
43
 
@@ -49,46 +45,62 @@ Un CLI en TypeScript y servidor MCP que carga canciones de piano desde [ai-music
49
45
  npm install -g @mcptoolshop/pianoai
50
46
  ```
51
47
 
48
+ Requiere **Node.js 18+**. Eso es todo — sin controladores MIDI, sin puertos virtuales, sin software externo.
49
+
52
50
  ## Inicio rápido
53
51
 
54
52
  ```bash
55
- # Listar todas las canciones
56
- pianoai list
53
+ # Reproducir un archivo MIDI
54
+ pianoai play path/to/song.mid
57
55
 
58
- # Mostrar detalles de canción + notas de enseñanza
59
- pianoai info moonlight-sonata-mvt1
56
+ # Reproducir con canto (narrar nombres de notas mientras suenan)
57
+ pianoai play song.mid --with-singing
60
58
 
61
- # Reproducir una canción a través de VMPK
62
- pianoai play let-it-be
59
+ # Cantar solo la melodía (omitir notas de acorde, solo la voz superior)
60
+ pianoai play song.mid --with-singing --voice-filter melody-only
63
61
 
64
- # Reproducir con modificación de tempo
65
- pianoai play basic-12-bar-blues --tempo 80
62
+ # Reproducir con retroalimentación de enseñanza (dinámica, estímulo)
63
+ pianoai play song.mid --with-teaching
66
64
 
67
- # Avanzar compás por compás
68
- pianoai play autumn-leaves --mode measure
65
+ # Reproducir con canto y enseñanza juntos
66
+ pianoai play song.mid --with-singing --with-teaching --sing-mode solfege
69
67
 
70
- # Práctica a mitad de velocidad
71
- pianoai play moonlight-sonata-mvt1 --speed 0.5
68
+ # Práctica a mitad de velocidad con canto
69
+ pianoai play song.mid --speed 0.5 --with-singing
72
70
 
73
- # Práctica lenta con manos separadas
74
- pianoai play dream-on --speed 0.75 --mode hands
71
+ # Saltar al segundo 45 y reproducir desde ahí
72
+ pianoai play song.mid --seek 45
75
73
 
76
- # Cantar junto narrar nombres de notas durante la reproducción
77
- pianoai sing let-it-be --mode note-names
74
+ # Reproducir una canción de la biblioteca integrada
75
+ pianoai play let-it-be
78
76
 
79
- # Cantar junto con solfeo, ambas manos
80
- pianoai sing fur-elise --mode solfege --hand both
77
+ # Listar todas las canciones integradas
78
+ pianoai list
81
79
 
82
- # Cantar + piano juntos (sensación de dúo)
83
- pianoai sing let-it-be --with-piano
80
+ # Mostrar detalles de canción + notas de enseñanza
81
+ pianoai info moonlight-sonata-mvt1
84
82
 
85
- # Voz primero, luego piano
86
- pianoai sing fur-elise --with-piano --sync before
83
+ # Cantar junto con una canción de la biblioteca (narración por voz)
84
+ pianoai sing let-it-be --mode solfege --with-piano
87
85
  ```
88
86
 
87
+ ### Opciones de reproducción
88
+
89
+ | Bandera | Descripción |
90
+ |---------|-------------|
91
+ | `--speed <mult>` | Multiplicador de velocidad: 0.5 = mitad, 1.0 = normal, 2.0 = doble |
92
+ | `--tempo <bpm>` | Modificar el tempo predeterminado de la canción (10-400 BPM) |
93
+ | `--mode <mode>` | Modo de reproducción: `full`, `measure`, `hands`, `loop` |
94
+ | `--with-singing` | Activar narración de canto en tiempo real |
95
+ | `--with-teaching` | Activar retroalimentación de enseñanza en vivo |
96
+ | `--sing-mode <mode>` | Modo de canto: `note-names`, `solfege`, `contour`, `syllables` |
97
+ | `--voice-filter <f>` | Filtro de voz: `all`, `melody-only`, `harmony` |
98
+ | `--seek <seconds>` | Saltar a un momento específico antes de reproducir |
99
+ | `--midi` | Enrutar a software MIDI externo en lugar del motor integrado |
100
+
89
101
  ## Servidor MCP
90
102
 
91
- El servidor MCP expone 8 herramientas para integración con LLMs:
103
+ El servidor MCP expone 12 herramientas para integración con LLMs:
92
104
 
93
105
  | Herramienta | Descripción |
94
106
  |-------------|-------------|
@@ -96,15 +108,14 @@ El servidor MCP expone 8 herramientas para integración con LLMs:
96
108
  | `song_info` | Obtener lenguaje musical completo, objetivos de enseñanza, sugerencias de práctica |
97
109
  | `registry_stats` | Conteo de canciones por género y dificultad |
98
110
  | `teaching_note` | Nota de enseñanza por compás, digitación, dinámicas |
99
- | `sing_along` | Obtener texto cantable por compás (nombres de notas, solfeo, contorno, sílabas); soporta `withPiano` para acompañamiento sincronizado |
100
111
  | `suggest_song` | Obtener una recomendación basada en criterios |
101
112
  | `list_measures` | Vista general de compases con notas de enseñanza + advertencias de análisis |
113
+ | `sing_along` | Obtener texto cantable (nombres de notas, solfeo, contorno, sílabas) por compás |
102
114
  | `practice_setup` | Sugerir velocidad, modo y configuración de voz para una canción |
103
-
104
- ```bash
105
- # Iniciar el servidor MCP (transporte stdio)
106
- pnpm mcp
107
- ```
115
+ | `play_song` | Reproducir una canción o archivo MIDI con canto y enseñanza opcionales |
116
+ | `pause_playback` | Pausar o reanudar la canción en reproducción |
117
+ | `set_speed` | Cambiar la velocidad de reproducción durante la reproducción |
118
+ | `stop_playback` | Detener la canción en reproducción |
108
119
 
109
120
  ### Configuración de Claude Desktop
110
121
 
@@ -112,195 +123,148 @@ pnpm mcp
112
123
  {
113
124
  "mcpServers": {
114
125
  "pianoai": {
115
- "command": "pianoai-mcp"
126
+ "command": "npx",
127
+ "args": ["-y", "-p", "@mcptoolshop/pianoai", "pianoai-mcp"]
116
128
  }
117
129
  }
118
130
  }
119
131
  ```
120
132
 
121
- ## Comandos del CLI
122
-
123
- | Comando | Descripción |
124
- |---------|-------------|
125
- | `list [--genre <genre>]` | Listar canciones disponibles, opcionalmente filtradas por género |
126
- | `info <song-id>` | Mostrar detalles de canción: lenguaje musical, notas de enseñanza, estructura |
127
- | `play <song-id> [opts]` | Reproducir una canción a través de VMPK vía MIDI |
128
- | `sing <song-id> [opts]` | Cantar junto — narrar notas durante la reproducción |
129
- | `stats` | Estadísticas del registro (canciones, géneros, compases) |
130
- | `ports` | Listar puertos de salida MIDI disponibles |
131
- | `help` | Mostrar información de uso |
133
+ ### play_song con canto y enseñanza
132
134
 
133
- ### Opciones de reproducción
135
+ La herramienta MCP `play_song` acepta las banderas `withSinging` y `withTeaching`:
134
136
 
135
- | Bandera | Descripción |
136
- |---------|-------------|
137
- | `--port <name>` | Nombre del puerto MIDI (por defecto: autodetectar loopMIDI) |
138
- | `--tempo <bpm>` | Modificar el tempo predeterminado de la canción (10-400 BPM) |
139
- | `--speed <mult>` | Multiplicador de velocidad: 0.5 = mitad, 1.0 = normal, 2.0 = doble |
140
- | `--mode <mode>` | Modo de reproducción: `full`, `measure`, `hands`, `loop` |
137
+ ```
138
+ play_song({ id: "path/to/song.mid", withSinging: true, withTeaching: true, singMode: "solfege" })
139
+ ```
141
140
 
142
- ### Opciones de canto
141
+ ## API programática
143
142
 
144
- | Bandera | Descripción |
145
- |---------|-------------|
146
- | `--mode <mode>` | Modo de canto: `note-names`, `solfege`, `contour`, `syllables` |
147
- | `--hand <hand>` | Qué mano: `right`, `left`, `both` |
148
- | `--with-piano` | Reproducir acompañamiento de piano mientras se canta |
149
- | `--sync <mode>` | Sincronización voz+piano: `concurrent` (por defecto, dúo), `before` (voz primero) |
143
+ ### Reproducir un archivo MIDI con controles en tiempo real
150
144
 
151
- ## Motor de enseñanza
145
+ ```typescript
146
+ import { createAudioEngine, parseMidiFile, PlaybackController } from "@mcptoolshop/pianoai";
152
147
 
153
- El motor de enseñanza dispara hooks durante la reproducción. 9 implementaciones de hooks cubren todos los casos de uso:
148
+ const connector = createAudioEngine();
149
+ await connector.connect();
154
150
 
155
- | Hook | Caso de uso |
156
- |------|-------------|
157
- | `createConsoleTeachingHook()` | CLI — registra compases, momentos y finalización en consola |
158
- | `createSilentTeachingHook()` | Testing — sin operación |
159
- | `createRecordingTeachingHook()` | Testing — graba eventos para aserciones |
160
- | `createCallbackTeachingHook(cb)` | Personalizado — redirige a cualquier callback asíncrono |
161
- | `createVoiceTeachingHook(sink)` | Voz — produce `VoiceDirective` para mcp-voice-soundboard |
162
- | `createAsideTeachingHook(sink)` | Aparte — produce `AsideDirective` para la bandeja de mcp-aside |
163
- | `createSingAlongHook(sink, song)` | Canto — narra notas/solfeo/contorno antes de cada compás |
164
- | `createLiveFeedbackHook(voiceSink, asideSink, song)` | Retroalimentación — estímulo, consejos de dinámica, avisos de dificultad |
165
- | `composeTeachingHooks(...hooks)` | Múltiple — despacha a múltiples hooks en serie |
151
+ const midi = await parseMidiFile("song.mid");
152
+ const controller = new PlaybackController(connector, midi);
166
153
 
167
- ### Retroalimentación por voz
154
+ // Escuchar eventos
155
+ controller.on("noteOn", (e) => console.log(`Nota: ${e.noteName}`));
156
+ controller.on("stateChange", (e) => console.log(`Estado: ${e.state}`));
168
157
 
169
- ```typescript
170
- import { createSession, createVoiceTeachingHook } from "@mcptoolshop/pianoai";
171
- import { getSong } from "ai-music-sheets";
172
-
173
- const voiceHook = createVoiceTeachingHook(
174
- async (directive) => {
175
- // Redirigir a voice_speak de mcp-voice-soundboard
176
- console.log(`[Voice] ${directive.text}`);
177
- },
178
- { voice: "narrator", speechSpeed: 0.9 }
179
- );
158
+ await controller.play({ speed: 0.75 });
180
159
 
181
- const session = createSession(getSong("moonlight-sonata-mvt1")!, connector, {
182
- teachingHook: voiceHook,
183
- speed: 0.5, // práctica a mitad de velocidad
184
- });
160
+ controller.pause(); // pausar
161
+ controller.setSpeed(1.5); // cambiar velocidad
162
+ await controller.resume();// reanudar a nueva velocidad
185
163
 
186
- await session.play();
187
- // voiceHook.directives → todas las instrucciones de voz que se dispararon
164
+ await connector.disconnect();
188
165
  ```
189
166
 
190
- ### Narración de canto
167
+ ### Reproducir con canto y enseñanza en vivo
191
168
 
192
169
  ```typescript
193
170
  import {
194
- createSingAlongHook,
195
- createVoiceTeachingHook,
171
+ createAudioEngine,
172
+ parseMidiFile,
173
+ PlaybackController,
174
+ createSingOnMidiHook,
175
+ createLiveMidiFeedbackHook,
196
176
  composeTeachingHooks,
197
- createSession,
198
177
  } from "@mcptoolshop/pianoai";
199
- import { getSong } from "@mcptoolshop/ai-music-sheets";
200
178
 
201
- const song = getSong("let-it-be")!;
202
-
203
- // Narrar solfeo antes de cada compás, luego notas de enseñanza
204
- const singHook = createSingAlongHook(voiceSink, song, {
205
- mode: "solfege",
206
- hand: "right",
207
- });
208
- const teachHook = createVoiceTeachingHook(voiceSink);
209
- const combined = composeTeachingHooks(singHook, teachHook);
179
+ const connector = createAudioEngine();
180
+ await connector.connect();
181
+ const midi = await parseMidiFile("song.mid");
210
182
 
211
- const session = createSession(song, connector, { teachingHook: combined });
212
- await session.play();
213
- // singHook.directives → "Do... Mi... Sol" bloqueante antes de cada compás
214
- ```
183
+ const singHook = createSingOnMidiHook(
184
+ async (d) => console.log(`♪ ${d.text}`),
185
+ midi,
186
+ { mode: "solfege", voiceFilter: "melody-only" }
187
+ );
215
188
 
216
- ### Composición de hooks
189
+ const feedbackHook = createLiveMidiFeedbackHook(
190
+ async (d) => console.log(`🎓 ${d.text}`),
191
+ async (d) => console.log(`💡 ${d.text}`),
192
+ midi,
193
+ { voiceInterval: 8 }
194
+ );
217
195
 
218
- ```typescript
219
- import {
220
- createVoiceTeachingHook,
221
- createAsideTeachingHook,
222
- createRecordingTeachingHook,
223
- composeTeachingHooks,
224
- } from "@mcptoolshop/pianoai";
196
+ const composed = composeTeachingHooks(singHook, feedbackHook);
197
+ const controller = new PlaybackController(connector, midi);
198
+ await controller.play({ teachingHook: composed });
225
199
 
226
- // Los tres se disparan en cada evento
227
- const composed = composeTeachingHooks(
228
- createVoiceTeachingHook(voiceSink),
229
- createAsideTeachingHook(asideSink),
230
- createRecordingTeachingHook()
231
- );
200
+ // feedbackHook.tracker tiene información de posición
201
+ console.log(`Total de compases: ${feedbackHook.tracker.totalMeasures}`);
232
202
  ```
233
203
 
234
- ## API programática
204
+ ### Reproducir una canción de la biblioteca integrada
235
205
 
236
206
  ```typescript
237
- import { getSong } from "ai-music-sheets";
238
- import { createSession, createVmpkConnector } from "@mcptoolshop/pianoai";
207
+ import { getSong } from "@mcptoolshop/ai-music-sheets";
208
+ import { createSession, createAudioEngine } from "@mcptoolshop/pianoai";
239
209
 
240
- const connector = createVmpkConnector({ portName: /loop/i });
210
+ const connector = createAudioEngine();
241
211
  await connector.connect();
242
212
 
243
213
  const song = getSong("autumn-leaves")!;
244
214
  const session = createSession(song, connector, {
245
- mode: "measure",
246
- tempo: 100,
247
- speed: 0.75, // 75% de velocidad para práctica
248
- onProgress: (p) => console.log(p.percent), // "25%", "50%", etc.
215
+ mode: "full",
216
+ speed: 0.75,
249
217
  });
250
218
 
251
- await session.play(); // reproduce un compás, pausa
252
- session.next(); // avanza al siguiente compás
253
- await session.play(); // reproduce el siguiente compás
254
- session.setSpeed(1.0); // vuelve a velocidad normal
255
- await session.play(); // reproduce el siguiente compás a velocidad completa
256
- session.stop(); // detiene y reinicia
257
-
258
- // Verificar advertencias de análisis (notas incorrectas en los datos de la canción)
259
- if (session.parseWarnings.length > 0) {
260
- console.warn("Algunas notas no pudieron ser analizadas:", session.parseWarnings);
261
- }
262
-
219
+ await session.play();
263
220
  await connector.disconnect();
264
221
  ```
265
222
 
266
223
  ## Arquitectura
267
224
 
268
225
  ```
269
- ai-music-sheets (biblioteca) pianoai (tiempo de ejecución)
270
- ┌──────────────────────┐ ┌────────────────────────────────┐
271
- │ SongEntry (híbrido) │────────→│ Note Parser (seguro + estricto)│
272
- Registry (búsqueda) │ │ Session Engine (veloc.+progreso│
273
- 10 canciones, 10 gén.│ Teaching Engine (9 hooks) │
274
- └──────────────────────┘ │ VMPK Connector (JZZ) │
275
- │ MCP Server (8 herramientas) │
276
- CLI (barra de progreso + voz)
277
- └─────────┬──────────────────────┘
278
- MIDI
279
-
280
- ┌─────────────────┐
281
- │ loopMIDI → VMPK │
282
- └─────────────────┘
226
+ Archivos MIDI estándar (.mid) Canciones integradas (ai-music-sheets)
227
+ │ │
228
+ ▼ ▼
229
+ MIDI Parser ──────────────── Note Parser
230
+
231
+ ▼ ▼
232
+ MidiPlaybackEngine SessionController
233
+
234
+ └──────── PlaybackController ──┘
235
+ (eventos en tiempo real, hooks)
236
+
237
+ ┌─────────────┼─────────────┐
238
+ ▼ ▼ ▼
239
+ AudioEngine Teaching Hooks Progress
240
+ (altavoces) (canto, retro.) (callbacks)
241
+
242
+
243
+ node-web-audio-api (Rust DSP)
244
+
245
+ Seguimiento de posición:
246
+ MIDI Parser → PositionTracker → mapeo de pulso/compás/tempo
247
+ → búsqueda por tiempo / búsqueda por compás
248
+ → resúmenes de compás para retroalimentación en vivo
283
249
 
284
250
  Enrutamiento de hooks de enseñanza:
285
- Session → TeachingHook → VoiceDirective → mcp-voice-soundboard
286
- → AsideDirective → bandeja de mcp-aside
287
- → Console log → terminal del CLI
288
- → Recording → aserciones de test
251
+ PlaybackController → TeachingHook → VoiceDirective → mcp-voice-soundboard
252
+ → AsideDirective → bandeja de mcp-aside
253
+ → Console log → terminal del CLI
254
+ → Recording → aserciones de test
289
255
  ```
290
256
 
291
257
  ## Testing
292
258
 
293
259
  ```bash
294
- pnpm test # 181 tests con Vitest (parser + session + teaching + voice + aside + sing-along)
295
- pnpm smoke # 29 smoke tests (integración, sin MIDI necesario)
260
+ pnpm test # 243 tests con Vitest
296
261
  pnpm typecheck # tsc --noEmit
262
+ pnpm smoke # tests de integración
297
263
  ```
298
264
 
299
- El conector VMPK simulado (`createMockVmpkConnector`) registra todos los eventos MIDI sin hardware, permitiendo cobertura completa de tests. Las funciones de análisis seguro (`safeParseMeasure`) recopilan objetos `ParseWarning` en lugar de lanzar excepciones, de modo que la reproducción continúa correctamente si una canción tiene notas malformadas.
300
-
301
265
  ## Relacionados
302
266
 
303
- - **[ai-music-sheets](https://github.com/mcp-tool-shop-org/ai-music-sheets)** — La biblioteca de canciones: 10 géneros, formato híbrido (metadatos + lenguaje musical + compases listos para código)
267
+ - **[ai-music-sheets](https://github.com/mcp-tool-shop-org/ai-music-sheets)** — La biblioteca de canciones integrada
304
268
 
305
269
  ## Licencia
306
270