mandioca-tabs-mcp 0.2.0 → 0.2.3
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.
- package/README.md +2 -2
- package/index.mjs +61 -12
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
Deja que tu asistente de IA lea y escriba la obra que tienes abierta en
|
|
4
4
|
[Mandioca Tabs](https://tabs.mandioca-records.com).
|
|
5
5
|
|
|
6
|
-
La guía de instalación para cada IA está dentro de Tabs: botón **
|
|
6
|
+
La guía de instalación para cada IA está dentro de Tabs: botón **Conectar IA**, en la barra
|
|
7
7
|
de abajo. En cualquier programa que acepte servidores MCP locales, el comando es:
|
|
8
8
|
|
|
9
9
|
```
|
|
10
10
|
npx -y mandioca-tabs-mcp
|
|
11
11
|
```
|
|
12
12
|
|
|
13
|
-
Después abre tu obra en Tabs y aprieta **Conectar
|
|
13
|
+
Después abre tu obra en Tabs y aprieta **Conectar IA**. La conexión es parte del plan Cowork.
|
package/index.mjs
CHANGED
|
@@ -19742,7 +19742,7 @@ var init_atajos = __esm({
|
|
|
19742
19742
|
// declara entre las superficies que esta cuenta no ve.
|
|
19743
19743
|
{ id: "guardar-grabacion", nombre: "Guardar la grabaci\xF3n elegida como .wav", grupo: "Audio y mezcla" },
|
|
19744
19744
|
{ id: "imantar", nombre: "Imantar los puntos de sync al golpe", grupo: "Audio y mezcla" },
|
|
19745
|
-
{ id: "solo-del-audio", nombre: "
|
|
19745
|
+
{ id: "solo-del-audio", nombre: "Aislar la grabaci\xF3n a la vista", grupo: "Audio y mezcla" },
|
|
19746
19746
|
{ id: "velocidad-mas", nombre: "Reproducir m\xE1s r\xE1pido", grupo: "Audio y mezcla" },
|
|
19747
19747
|
{ id: "velocidad-menos", nombre: "Reproducir m\xE1s lento", grupo: "Audio y mezcla" },
|
|
19748
19748
|
// ★ Agregado el 2026-09-03. Va en «Audio y mezcla» y no en un grupo propio porque es lo que
|
|
@@ -25101,7 +25101,7 @@ var init_paneles = __esm({
|
|
|
25101
25101
|
"audio.solo": {
|
|
25102
25102
|
nombre: "Solo de la grabaci\xF3n",
|
|
25103
25103
|
accion: "audio-solo-del-audio",
|
|
25104
|
-
principiante: "Prendido, se oye s\xF3lo la
|
|
25104
|
+
principiante: "Prendido, de las grabaciones se oye s\xF3lo la que est\xE1s viendo, junto con la partitura. Apagado, suena lo que diga la mezcla.",
|
|
25105
25105
|
profesional: "Solo que sigue a la grabaci\xF3n a la vista."
|
|
25106
25106
|
},
|
|
25107
25107
|
"audio.velocidad": {
|
|
@@ -25195,6 +25195,11 @@ var init_paneles = __esm({
|
|
|
25195
25195
|
principiante: "Guarda en tu computadora la grabaci\xF3n que se est\xE1 mirando, como archivo WAV. Sirve para sacar un stem.",
|
|
25196
25196
|
profesional: "Exporta la grabaci\xF3n elegida a WAV."
|
|
25197
25197
|
},
|
|
25198
|
+
"audio.sync-to": {
|
|
25199
|
+
nombre: "Sync to",
|
|
25200
|
+
principiante: "Las dem\xE1s grabaciones quedan sincronizadas igual que \xE9sta: cada comp\xE1s anclado cae en el mismo segundo. Reemplaza los anclajes que ten\xEDan. Se deshace con Ctrl + Z.",
|
|
25201
|
+
profesional: "Copia los puntos de sync de esta grabaci\xF3n a las dem\xE1s (reemplaza)."
|
|
25202
|
+
},
|
|
25198
25203
|
"audio.quitar": {
|
|
25199
25204
|
nombre: "Dejar de o\xEDrla",
|
|
25200
25205
|
accion: "audio-quitar",
|
|
@@ -96396,6 +96401,15 @@ var init_sync = __esm({
|
|
|
96396
96401
|
}
|
|
96397
96402
|
});
|
|
96398
96403
|
|
|
96404
|
+
// apps/mcp/src/version.ts
|
|
96405
|
+
var VERSION_DEL_CONECTOR;
|
|
96406
|
+
var init_version = __esm({
|
|
96407
|
+
"apps/mcp/src/version.ts"() {
|
|
96408
|
+
"use strict";
|
|
96409
|
+
VERSION_DEL_CONECTOR = true ? "0.2.3" : null;
|
|
96410
|
+
}
|
|
96411
|
+
});
|
|
96412
|
+
|
|
96399
96413
|
// apps/mcp/src/puente.ts
|
|
96400
96414
|
var puente_exports = {};
|
|
96401
96415
|
__export(puente_exports, {
|
|
@@ -96488,7 +96502,7 @@ function exigirPesta\u00F1a() {
|
|
|
96488
96502
|
const p = puenteAbierto();
|
|
96489
96503
|
if (p.pesta\u00F1as() === 0) {
|
|
96490
96504
|
throw new ProblemaConLaObra(
|
|
96491
|
-
`El puente est\xE1 abierto en el puerto ${p.puerto} pero no hay ninguna pesta\xF1a de Mandioca Tabs conectada. Abre el programa en el navegador y aprieta \xABConectar
|
|
96505
|
+
`El puente est\xE1 abierto en el puerto ${p.puerto} pero no hay ninguna pesta\xF1a de Mandioca Tabs conectada. Abre el programa en el navegador y aprieta \xABConectar IA\xBB, el bot\xF3n de la barra de estado (abajo del todo, dice \xABConectar IA\xBB). Esto no se puede hacer sin la aplicaci\xF3n abierta: sonar, ver, seleccionar y sacar una captura s\xF3lo existen en el navegador.`
|
|
96492
96506
|
);
|
|
96493
96507
|
}
|
|
96494
96508
|
return p;
|
|
@@ -96577,6 +96591,11 @@ function atenderElMostrador(pedido, respuesta) {
|
|
|
96577
96591
|
respuesta.writeHead(204).end();
|
|
96578
96592
|
return;
|
|
96579
96593
|
}
|
|
96594
|
+
if (ruta === "/version") {
|
|
96595
|
+
respuesta.writeHead(200, { "Content-Type": "application/json" });
|
|
96596
|
+
respuesta.end(JSON.stringify({ version: VERSION_DEL_CONECTOR }));
|
|
96597
|
+
return;
|
|
96598
|
+
}
|
|
96580
96599
|
if (ruta.startsWith("/subir/")) {
|
|
96581
96600
|
recibirEnElCasillero(ruta.slice("/subir/".length), pedido, respuesta);
|
|
96582
96601
|
return;
|
|
@@ -96824,7 +96843,7 @@ async function canalDePedidos(p, herramienta) {
|
|
|
96824
96843
|
id2 = conectadas[0].id;
|
|
96825
96844
|
} else {
|
|
96826
96845
|
throw new ProblemaConLaObra(
|
|
96827
|
-
`\xAB${herramienta}\xBB s\xF3lo puede hacerlo la aplicaci\xF3n, y no se sabe cu\xE1l. ` + (conectadas.length === 0 ? "No hay ninguna pesta\xF1a conectada: p\xEDdele al m\xFAsico que abra Mandioca Tabs y apriete \xABConectar
|
|
96846
|
+
`\xAB${herramienta}\xBB s\xF3lo puede hacerlo la aplicaci\xF3n, y no se sabe cu\xE1l. ` + (conectadas.length === 0 ? "No hay ninguna pesta\xF1a conectada: p\xEDdele al m\xFAsico que abra Mandioca Tabs y apriete \xABConectar IA\xBB, el bot\xF3n de la barra de estado." : `Hay ${conectadas.length} obras conectadas: ${lista2}. Elige una con \`elegir_obra\`, por su letra, y rep\xEDtelo \u2014 adivinar entre varias har\xEDa que suene, o se cargue, la canci\xF3n equivocada.`)
|
|
96828
96847
|
);
|
|
96829
96848
|
}
|
|
96830
96849
|
}
|
|
@@ -96917,6 +96936,7 @@ var init_puente = __esm({
|
|
|
96917
96936
|
init_src2();
|
|
96918
96937
|
init_src3();
|
|
96919
96938
|
init_obra();
|
|
96939
|
+
init_version();
|
|
96920
96940
|
envoltoriosPorDoc = /* @__PURE__ */ new WeakMap();
|
|
96921
96941
|
SINCRONIZAR = 0;
|
|
96922
96942
|
PRESENCIA = 1;
|
|
@@ -96966,7 +96986,7 @@ function laPesta\u00F1aSigueViva() {
|
|
|
96966
96986
|
function obraAbierta() {
|
|
96967
96987
|
if (abierta && !laPesta\u00F1aSigueViva()) {
|
|
96968
96988
|
throw new ProblemaConLaObra(
|
|
96969
|
-
"La pesta\xF1a de Mandioca Tabs se desconect\xF3. Lo \xFAltimo que se sincroniz\xF3 sigue en memoria, pero **ya no es lo que el m\xFAsico tiene en pantalla** y escribir ah\xED no lo ver\xEDa nadie. P\xEDdele que vuelva a abrir el programa y apriete \xABConectar
|
|
96989
|
+
"La pesta\xF1a de Mandioca Tabs se desconect\xF3. Lo \xFAltimo que se sincroniz\xF3 sigue en memoria, pero **ya no es lo que el m\xFAsico tiene en pantalla** y escribir ah\xED no lo ver\xEDa nadie. P\xEDdele que vuelva a abrir el programa y apriete \xABConectar IA\xBB, el bot\xF3n de la barra de estado."
|
|
96970
96990
|
);
|
|
96971
96991
|
}
|
|
96972
96992
|
if (!abierta) {
|
|
@@ -97324,6 +97344,18 @@ var init_estilo = __esm({
|
|
|
97324
97344
|
});
|
|
97325
97345
|
|
|
97326
97346
|
// packages/projection/src/proyectar.ts
|
|
97347
|
+
function canalesDeLasPistas(tipos) {
|
|
97348
|
+
const libres = Array.from({ length: 16 }, (_, i2) => i2).filter((c) => c !== 9);
|
|
97349
|
+
const conAltura = tipos.filter((t) => t !== "percusion").length;
|
|
97350
|
+
const porPista = conAltura * 2 <= libres.length ? 2 : 1;
|
|
97351
|
+
let siguiente = 0;
|
|
97352
|
+
const tomar = () => libres[siguiente++ % libres.length];
|
|
97353
|
+
return tipos.map((tipo) => {
|
|
97354
|
+
if (tipo === "percusion") return [9, 9];
|
|
97355
|
+
const primario = tomar();
|
|
97356
|
+
return [primario, porPista === 2 ? tomar() : primario];
|
|
97357
|
+
});
|
|
97358
|
+
}
|
|
97327
97359
|
function proyectar(documento, opciones = {}) {
|
|
97328
97360
|
const ajustes = opciones.ajustes ?? new Settings();
|
|
97329
97361
|
const score = new _barrel_exports$4.Score();
|
|
@@ -97414,9 +97446,14 @@ function proyectar(documento, opciones = {}) {
|
|
|
97414
97446
|
if (lista2) lista2.push(nota);
|
|
97415
97447
|
else notasPorFigura.set(nota.figuraId, [nota]);
|
|
97416
97448
|
}
|
|
97417
|
-
|
|
97449
|
+
const pistasEnOrden = [...documento.pistasEnOrden()];
|
|
97450
|
+
const canales = canalesDeLasPistas(
|
|
97451
|
+
pistasEnOrden.map(({ datos }) => normalizarPista(datos).tipo)
|
|
97452
|
+
);
|
|
97453
|
+
for (const [indiceDePista, { id: idPista, datos }] of pistasEnOrden.entries()) {
|
|
97418
97454
|
const pista = normalizarPista(datos);
|
|
97419
97455
|
const track = new _barrel_exports$4.Track();
|
|
97456
|
+
[track.playbackInfo.primaryChannel, track.playbackInfo.secondaryChannel] = canales[indiceDePista];
|
|
97420
97457
|
track.name = marcado(pista.nombre, pista.nombreSegundaTipografia);
|
|
97421
97458
|
track.shortName = marcado(pista.nombreCorto, pista.nombreCortoSegundaTipografia);
|
|
97422
97459
|
track.playbackInfo.program = pista.programaMidi;
|
|
@@ -122340,6 +122377,9 @@ function registrarHerramientasDelDocumento(servidor2) {
|
|
|
122340
122377
|
);
|
|
122341
122378
|
}
|
|
122342
122379
|
|
|
122380
|
+
// apps/mcp/src/servidor.ts
|
|
122381
|
+
init_version();
|
|
122382
|
+
|
|
122343
122383
|
// apps/mcp/src/herramientas/puente.ts
|
|
122344
122384
|
init_src2();
|
|
122345
122385
|
init_src3();
|
|
@@ -122371,7 +122411,7 @@ function registrarHerramientasDelPuente(servidor2) {
|
|
|
122371
122411
|
"conectar_con_la_app",
|
|
122372
122412
|
{
|
|
122373
122413
|
title: "Conectar con la aplicaci\xF3n abierta",
|
|
122374
|
-
description: "Se engancha a la obra que el m\xFAsico tiene abierta en el navegador, en vez de a un archivo del disco. A partir de ac\xE1, lo que se escriba aparece en su pantalla y lo que \xE9l escriba se ve desde ac\xE1. Requiere que \xE9l apriete \xABConectar
|
|
122414
|
+
description: "Se engancha a la obra que el m\xFAsico tiene abierta en el navegador, en vez de a un archivo del disco. A partir de ac\xE1, lo que se escriba aparece en su pantalla y lo que \xE9l escriba se ve desde ac\xE1. Requiere que \xE9l apriete \xABConectar IA\xBB, el bot\xF3n de la barra de estado (abajo del todo, dice \xABConectar IA\xBB).",
|
|
122375
122415
|
inputSchema: {
|
|
122376
122416
|
puerto: external_exports.number().int().min(1024).max(65535).optional().describe(`El puerto del puente. Por omisi\xF3n ${PUERTO_POR_OMISION}.`)
|
|
122377
122417
|
}
|
|
@@ -122390,7 +122430,7 @@ function registrarHerramientasDelPuente(servidor2) {
|
|
|
122390
122430
|
pesta\u00F1asConectadas: p.pesta\u00F1as(),
|
|
122391
122431
|
// ⚠️ Se dice lo que falta, sin adornarlo. Si no hay pestaña, el asistente tiene que
|
|
122392
122432
|
// saberlo ANTES de prometerle algo al músico — no descubrirlo al primer fallo.
|
|
122393
|
-
siguiente: conectadas.length > 1 ? `Hay ${conectadas.length} obras abiertas. Mira \`obras_conectadas\` y elige una con \`elegir_obra\`, por su letra, antes de escribir nada.` : p.pesta\u00F1as() > 0 ? "Ya hay una pesta\xF1a conectada: la obra que se lee y se escribe es la suya." : "Todav\xEDa no hay ninguna pesta\xF1a. P\xEDdele que abra Mandioca Tabs y active P\xEDdele que apriete \xABConectar
|
|
122433
|
+
siguiente: conectadas.length > 1 ? `Hay ${conectadas.length} obras abiertas. Mira \`obras_conectadas\` y elige una con \`elegir_obra\`, por su letra, antes de escribir nada.` : p.pesta\u00F1as() > 0 ? "Ya hay una pesta\xF1a conectada: la obra que se lee y se escribe es la suya." : "Todav\xEDa no hay ninguna pesta\xF1a. P\xEDdele que abra Mandioca Tabs y active P\xEDdele que apriete \xABConectar IA\xBB, el bot\xF3n de la barra de estado (abajo del todo, dice \xABConectar IA\xBB)."
|
|
122394
122434
|
});
|
|
122395
122435
|
}
|
|
122396
122436
|
);
|
|
@@ -122414,7 +122454,7 @@ function registrarHerramientasDelPuente(servidor2) {
|
|
|
122414
122454
|
...o.id === idDeLaActiva ? { activa: true } : {}
|
|
122415
122455
|
})),
|
|
122416
122456
|
activa: activa ? comoSeLlama(activa) : null,
|
|
122417
|
-
siguiente: conectadas.length === 0 ? "No hay ninguna. P\xEDdele que abra Mandioca Tabs y apriete \xABConectar
|
|
122457
|
+
siguiente: conectadas.length === 0 ? "No hay ninguna. P\xEDdele que abra Mandioca Tabs y apriete \xABConectar IA\xBB." : activa === null ? "Hay varias y ninguna elegida: `elegir_obra` con su letra antes de escribir." : conectadas.length > 1 ? `Se escribe en la ${activa.etiqueta} (\xAB${activa.titulo}\xBB). Para otra, \`elegir_obra\` con su letra.` : "Hay una sola y est\xE1 viva: es la activa."
|
|
122418
122458
|
});
|
|
122419
122459
|
}
|
|
122420
122460
|
);
|
|
@@ -122703,6 +122743,15 @@ function registrarHerramientasDelPuente(servidor2) {
|
|
|
122703
122743
|
// no cree nada que la interfaz no alcance — que es la que se pagó cuatro veces hoy.
|
|
122704
122744
|
async () => texto3(await pedirALaPesta\u00F1a("desanclar_todo", {}))
|
|
122705
122745
|
);
|
|
122746
|
+
servidor2.registerTool(
|
|
122747
|
+
"sync_to",
|
|
122748
|
+
{
|
|
122749
|
+
title: "Sync to: igualar las dem\xE1s grabaciones a la elegida",
|
|
122750
|
+
description: "Es el bot\xF3n \xABSync to\xBB del panel de audio. Las DEM\xC1S grabaciones de la obra quedan con la sincronizaci\xF3n de la elegida: los mismos compases anclados en los mismos milisegundos, y el mismo ritmo antes del primer anclaje y despu\xE9s del \xFAltimo. Contesta cu\xE1ntas grabaciones igual\xF3 y cu\xE1ntos puntos les copi\xF3. \u26A0\uFE0F Reemplaza los anclajes que ten\xEDan las dem\xE1s. Sirve cuando los audios arrancan juntos (stems o tomas del mismo proyecto); no compensa un desfase entre archivos. \u26A0\uFE0F No toca la letra sincronizada. Entra en el deshacer, como cualquier edici\xF3n.",
|
|
122751
|
+
inputSchema: {}
|
|
122752
|
+
},
|
|
122753
|
+
async () => texto3(await pedirALaPesta\u00F1a("sync_to", {}))
|
|
122754
|
+
);
|
|
122706
122755
|
servidor2.registerTool(
|
|
122707
122756
|
"quitar_grabacion",
|
|
122708
122757
|
{
|
|
@@ -122773,8 +122822,8 @@ function registrarHerramientasDelPuente(servidor2) {
|
|
|
122773
122822
|
servidor2.registerTool(
|
|
122774
122823
|
"solo_del_audio",
|
|
122775
122824
|
{
|
|
122776
|
-
title: "
|
|
122777
|
-
description: "Con esto puesto se oye s\xF3lo la
|
|
122825
|
+
title: "Aislar la grabaci\xF3n a la vista",
|
|
122826
|
+
description: "Con esto puesto, de las grabaciones se oye s\xF3lo la que muestra el panel de audio; la tablatura sigue sonando, para comparar con ella. Las dem\xE1s grabaciones se callan, y sigue a la que se elija con `elegir_grabacion`. Apagado, suena la mezcla como estaba. Prenderlo abre el panel. Sin decir nada, alterna. Con `volumenDb` fija el volumen de esa grabaci\xF3n en Solo; antes del fader, s\xF3lo cuenta con Solo puesto. Contesta `topeDb`: hasta +12 dB, o menos si m\xE1s arriba picar\xEDa.",
|
|
122778
122827
|
inputSchema: {
|
|
122779
122828
|
puesto: external_exports.boolean().optional().describe("true lo enciende, false lo apaga. Sin esto, alterna."),
|
|
122780
122829
|
volumenDb: external_exports.number().min(-60).max(12).optional().describe("Volumen en Solo de la grabaci\xF3n a la vista, en dB.")
|
|
@@ -125482,7 +125531,7 @@ function registrarHerramientasDeArchivo(servidor2) {
|
|
|
125482
125531
|
|
|
125483
125532
|
// apps/mcp/src/servidor.ts
|
|
125484
125533
|
var NOMBRE = "mandioca-tabs";
|
|
125485
|
-
var VERSION = "0.0.0";
|
|
125534
|
+
var VERSION = VERSION_DEL_CONECTOR ?? "0.0.0";
|
|
125486
125535
|
var INSTRUCCIONES = `
|
|
125487
125536
|
Mandioca Tabs es un editor de partitura y tablatura. Estas herramientas leen y escriben la
|
|
125488
125537
|
obra del m\xFAsico.
|
package/package.json
CHANGED