@hidechae/eztab-mcp 0.4.0 → 0.4.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.
- package/dist/server.js +18 -4
- package/package.json +1 -1
package/dist/server.js
CHANGED
|
@@ -724,6 +724,18 @@ function parseBeat(text2, stringCount, where) {
|
|
|
724
724
|
return { cells, chord };
|
|
725
725
|
});
|
|
726
726
|
}
|
|
727
|
+
var STRAIGHT = [1, 2, 4, 8];
|
|
728
|
+
function uniformBeats(beats) {
|
|
729
|
+
const target = Math.max(0, ...beats.map((b) => b.length).filter((n) => STRAIGHT.includes(n)));
|
|
730
|
+
return beats.map((slots) => {
|
|
731
|
+
if (!STRAIGHT.includes(slots.length) || slots.length === target) return slots;
|
|
732
|
+
const step = target / slots.length;
|
|
733
|
+
return Array.from(
|
|
734
|
+
{ length: target },
|
|
735
|
+
(_, i) => i % step === 0 ? slots[i / step] : { cells: /* @__PURE__ */ new Map(), chord: null }
|
|
736
|
+
);
|
|
737
|
+
});
|
|
738
|
+
}
|
|
727
739
|
function buildMeasure(spec, stringCount, fallback, where = "measure") {
|
|
728
740
|
const time = spec.time ? parseTime(spec.time) : fallback;
|
|
729
741
|
if (spec.beats.length !== time.beats) {
|
|
@@ -731,7 +743,9 @@ function buildMeasure(spec, stringCount, fallback, where = "measure") {
|
|
|
731
743
|
`${where}: ${spec.beats.length} beats given but the time signature ${time.beats}/${time.beatUnit} has ${time.beats}`
|
|
732
744
|
);
|
|
733
745
|
}
|
|
734
|
-
const beats =
|
|
746
|
+
const beats = uniformBeats(
|
|
747
|
+
spec.beats.map((b, i) => parseBeat(b, stringCount, `${where} beat ${i + 1}`))
|
|
748
|
+
);
|
|
735
749
|
const measure = createMeasure(
|
|
736
750
|
stringCount,
|
|
737
751
|
time.beats,
|
|
@@ -861,7 +875,7 @@ var IMPORT_TAB_FROM_IMAGE = `Transcribe the TAB in the attached image(s) into an
|
|
|
861
875
|
|
|
862
876
|
## 2. Write bar by bar with write_measures
|
|
863
877
|
Read each bar's rhythm first (beams, flags, dots, tuplet brackets, rests), then the fret numbers, then write it. Send a few bars per call, in order. In a fresh document the first bar goes to measure 0 (replacing the empty measure new_tab made); after that append at the current measure count.
|
|
864
|
-
- Subdivision per beat = the fewest slots that put every onset of the beat on a slot: quarter \u2192 1, eighths \u2192 2, 16ths or dotted-8th + 16th \u2192 4, triplet \u2192 3. Only onsets are stored; a held note is just empty slots ("-") after it.
|
|
878
|
+
- Subdivision per beat = the fewest slots that put every onset of the beat on a slot: quarter \u2192 1, eighths \u2192 2, 16ths or dotted-8th + 16th \u2192 4, triplet \u2192 3. Only onsets are stored; a held note is just empty slots ("-") after it. write_measures then evens out the straight beats of each measure to the finest one (a bar with any 16ths is stored all in 16ths; triplet / sextuplet beats stay as they are), so you do not need to pad beats yourself.
|
|
865
879
|
- Use the TAB numbers for frets, and the staff notation (when present) to settle rhythm and ambiguous digits. String 1 is the TOP line of the TAB.
|
|
866
880
|
- Chord names printed above the staff go on the chord row with @Name at the slot where the chord changes (usually beat 1).
|
|
867
881
|
- Rests: write S:r on the string that was ringing only when the line clearly stops (a rest symbol); otherwise leave "-".
|
|
@@ -893,7 +907,7 @@ var state = {
|
|
|
893
907
|
source: null
|
|
894
908
|
};
|
|
895
909
|
var server = new McpServer(
|
|
896
|
-
{ name: "eztab", version: "0.4.
|
|
910
|
+
{ name: "eztab", version: "0.4.1" },
|
|
897
911
|
{
|
|
898
912
|
instructions: "All indices are 0-based: measure 0 is the first measure, string 0 is the top (highest) string, and column 0 is the first column. Notes and chords share the same column grid. Subdivisions are per beat and can differ within a measure (e.g. [2,2,3,2] mixes a triplet beat into straight eighths), so columns per measure = the sum of its per-beat subdivisions; get_tab's ruler shows the column indices. add_measures `at` is a 0-based insert position too. No need to ask the user about indexing. Exception: write_measures uses guitar string numbers (1 = top line), matching the labels get_tab prints. To write whole measures (e.g. transcribing a score or an image), prefer write_measures over set_cells \u2014 it takes one string per beat and does the column arithmetic for you. For transcribing from an image, follow the import_tab_from_image prompt. To deliver a result to the EZTab app, call send_to_eztab; to fix an existing tab, list_tabs \u2192 open_tab \u2192 edit \u2192 send_to_eztab. A tab can hold up to 4 tracks (parts, e.g. guitar + bass); track 0 is the main track. Tools that edit notes take an optional 0-based `track` (default 0). Measures and time signatures are shared by all tracks (adding/removing a measure affects every track); subdivisions are per track; chords belong to track 0 and use its columns."
|
|
899
913
|
}
|
|
@@ -1141,7 +1155,7 @@ server.tool(
|
|
|
1141
1155
|
);
|
|
1142
1156
|
server.tool(
|
|
1143
1157
|
"write_measures",
|
|
1144
|
-
'Write whole measures, one text string per beat \u2014 the easiest way to transcribe a score. Each listed measure is replaced entirely (notes, chords, per-beat subdivisions). `measure` is the 0-based index; using the current measure count appends, so a transcription can be written in order without add_measures. `time` (e.g. "4/4", "6/8") is optional: it defaults to the measure being replaced, or the previous measure when appending. `beats` has exactly one string per beat of the time signature.\n\nA beat string is space-separated slots; the slot count is that beat\'s subdivision (1 = quarter, 2 = eighths, 3 = eighth triplet, 4 = sixteenths, 6 = sixteenth triplet \u2026). Pick the smallest count that puts every onset of the beat on a slot (a dotted eighth + sixteenth = 4 slots: note - - note). A slot is "-" (nothing starts there; the previous note rings on) or items joined by "+":\n S:F string S (1 = top line of the TAB, as printed) at fret F\n S:~F tied / slurred from the previous note on that string (hammer-on, pull-off, slide into F, or a tie when F is the same fret)\n S:Fb / S:FB / S:F^ choke (bend) \xBD / 1 / 1\xBD steps\n S:Fp palm (bridge) mute; combines, e.g. S:~5p, S:7Bp\n S:<P> natural harmonic touched at fret P (S:<12>, S:<7>; between frets S:<2.4>)\n S:F<P> artificial harmonic: fret F, harmonic at P (S:7<19>); S:Fa = artificial, position not written\n S:Fh pinch harmonic (P.H.); S:F<P>h = pinch harmonic at P (S:7<19>h)\n S:x muted dead-note stroke (brushing)\n S:r rest: stops the note ringing on that string\n @Name chord name onset for the chord row (e.g. @Am7, @N.C.)\nExamples: ["6:5 6:7", "5:5 5:7", "4:5 - 4:7", "@F+4:3+3:2+2:1+1:1"].',
|
|
1158
|
+
'Write whole measures, one text string per beat \u2014 the easiest way to transcribe a score. Each listed measure is replaced entirely (notes, chords, per-beat subdivisions). `measure` is the 0-based index; using the current measure count appends, so a transcription can be written in order without add_measures. `time` (e.g. "4/4", "6/8") is optional: it defaults to the measure being replaced, or the previous measure when appending. `beats` has exactly one string per beat of the time signature.\n\nA beat string is space-separated slots; the slot count is that beat\'s subdivision (1 = quarter, 2 = eighths, 3 = eighth triplet, 4 = sixteenths, 6 = sixteenth triplet \u2026). Pick the smallest count that puts every onset of the beat on a slot (a dotted eighth + sixteenth = 4 slots: note - - note). Within a measure the straight beats are evened out to the finest one (a quarter-note beat next to a sixteenth beat is stored as 4 slots), so write each beat as is; tuplet beats keep their own count. A slot is "-" (nothing starts there; the previous note rings on) or items joined by "+":\n S:F string S (1 = top line of the TAB, as printed) at fret F\n S:~F tied / slurred from the previous note on that string (hammer-on, pull-off, slide into F, or a tie when F is the same fret)\n S:Fb / S:FB / S:F^ choke (bend) \xBD / 1 / 1\xBD steps\n S:Fp palm (bridge) mute; combines, e.g. S:~5p, S:7Bp\n S:<P> natural harmonic touched at fret P (S:<12>, S:<7>; between frets S:<2.4>)\n S:F<P> artificial harmonic: fret F, harmonic at P (S:7<19>); S:Fa = artificial, position not written\n S:Fh pinch harmonic (P.H.); S:F<P>h = pinch harmonic at P (S:7<19>h)\n S:x muted dead-note stroke (brushing)\n S:r rest: stops the note ringing on that string\n @Name chord name onset for the chord row (e.g. @Am7, @N.C.)\nExamples: ["6:5 6:7", "5:5 5:7", "4:5 - 4:7", "@F+4:3+3:2+2:1+1:1"].',
|
|
1145
1159
|
{
|
|
1146
1160
|
measures: z.array(
|
|
1147
1161
|
z.object({
|