frascuchon HF Staff commited on
Commit
122c63e
·
1 Parent(s): 27f7430

fix mcp tools inputs

Browse files
Files changed (1) hide show
  1. mcp_server.py +77 -58
mcp_server.py CHANGED
@@ -112,7 +112,7 @@ def stretch_audio_to_bpm_wrapper(audio_path: str, target_bpm: float) -> str:
112
 
113
  def extract_selected_stems_wrapper(
114
  audio_path: str, vocals: bool, drums: bool, bass: bool, other: bool
115
- ) -> Dict[str, str]:
116
  """
117
  Extract selected stems from an audio file based on user choices.
118
 
@@ -127,7 +127,7 @@ def extract_selected_stems_wrapper(
127
  other: Whether to extract the other stem
128
 
129
  Returns:
130
- dict[str, str]: Dictionary mapping stem names to their file paths
131
 
132
  Examples:
133
  >>> extract_selected_stems_wrapper("song.wav", True, True, False, False)
@@ -157,7 +157,14 @@ def extract_selected_stems_wrapper(
157
  if not stems_to_extract:
158
  raise ValueError("At least one stem must be selected for extraction")
159
 
160
- return extract_selected_stems(audio_path, stems_to_extract)
 
 
 
 
 
 
 
161
 
162
 
163
  def extract_vocal_non_vocal_wrapper(audio_path: str) -> Tuple[str, str]:
@@ -261,9 +268,9 @@ def mute_time_windows_wrapper(
261
 
262
  def extract_segments_wrapper(
263
  audio_path: str, segments_str: str, format_val: str, join: bool
264
- ) -> str | None:
265
  """
266
- Extract multiple segments from an audio file and optionally join them.
267
 
268
  This wrapper function parses JSON-formatted time segments and extracts
269
  the specified portions from the audio file, with an option to join
@@ -305,12 +312,18 @@ def extract_segments_wrapper(
305
  output_format=format_val,
306
  join_segments=join,
307
  )
308
- # If result is a list, return the first item for Gradio
 
309
  if isinstance(result, list):
310
- return result[0] if result else None
311
- return result
312
- except Exception:
313
- return None
 
 
 
 
 
314
 
315
 
316
  def analyze_music_structure_wrapper(audio_path: str) -> str:
@@ -669,11 +682,11 @@ def shift_to_key_wrapper(
669
  # MCP Tool Wrappers with Documentation for MCP Server
670
 
671
 
672
- def separate_audio_mcp(audio_path: str, output_format: str = "wav") -> Dict[str, str]:
673
  """
674
  Separate audio into vocals, drums, bass, and other stems using Demucs neural network.
675
 
676
- This MCP tool uses the Demucs model to isolate individual instrument stems from a mixed
677
  audio file, providing high-quality separation for music production, remixing, and analysis.
678
 
679
  Args:
@@ -681,17 +694,12 @@ def separate_audio_mcp(audio_path: str, output_format: str = "wav") -> Dict[str,
681
  output_format: Output format for separated stems ('wav' or 'mp3', default: 'wav')
682
 
683
  Returns:
684
- Dictionary with paths to separated audio files:
685
- {
686
- "vocals": "path/to/vocals.wav",
687
- "drums": "path/to/drums.wav",
688
- "bass": "path/to/bass.wav",
689
- "other": "path/to/other.wav"
690
- }
691
 
692
  Examples:
693
  >>> separate_audio_mcp("song.mp3", "wav")
694
- # Returns {'vocals': '/tmp/vocals.wav', 'drums': '/tmp/drums.wav', ...}
695
 
696
  Note:
697
  - Processing time varies with audio length and complexity
@@ -705,14 +713,9 @@ def separate_audio_mcp(audio_path: str, output_format: str = "wav") -> Dict[str,
705
  output_path=None, # Use default temp location
706
  output_format=output_format,
707
  )
708
- return {
709
- "vocals": vocals,
710
- "drums": drums,
711
- "bass": bass,
712
- "other": other,
713
- }
714
  except Exception as e:
715
- return {"error": f"Error separating audio: {str(e)}"}
716
 
717
 
718
  def combine_tracks_mcp(
@@ -721,6 +724,8 @@ def combine_tracks_mcp(
721
  weight1: float = 0.5,
722
  weight2: float = 0.5,
723
  normalize: bool = True,
 
 
724
  output_format: str = "wav",
725
  ) -> str:
726
  """
@@ -735,16 +740,18 @@ def combine_tracks_mcp(
735
  weight1: Mixing weight for track1 (0.0 to 1.0, default: 0.5)
736
  weight2: Mixing weight for track2 (0.0 to 1.0, default: 0.5)
737
  normalize: Whether to normalize the output to prevent clipping (default: True)
 
 
738
  output_format: Output format for combined audio ('wav' or 'mp3', default: 'wav')
739
 
740
  Returns:
741
  Path to the combined audio file
742
 
743
  Examples:
744
- >>> combine_tracks_mcp("vocals.wav", "instrumental.wav", 0.6, 0.4, True, "wav")
745
  # Returns 'path/to/combined.wav' with vocals at 60%, instrumental at 40%
746
 
747
- >>> combine_tracks_mcp("drums.mp3", "bass.mp3", 0.7, 0.3, False, "mp3")
748
  # Returns 'path/to/combined.mp3' without normalization
749
 
750
  Note:
@@ -761,8 +768,8 @@ def combine_tracks_mcp(
761
  weight2=weight2,
762
  output_path=None, # Use default temp location
763
  normalize=normalize,
764
- fade_in=0.0, # No fade by default for MCP
765
- fade_out=0.0, # No fade by default for MCP
766
  output_format=output_format,
767
  )
768
  return result
@@ -869,6 +876,7 @@ def create_medley_mcp(
869
  including gain control, compression, and high-quality mixing for polished results.
870
 
871
  Args:
 
872
  vocals_path: Path to the vocals audio file or URL (supports common formats: WAV, MP3, FLAC, M4A)
873
  instrumental_path: Path to the instrumental audio file or URL (supports common formats: WAV, MP3, FLAC, M4A)
874
  vocals_gain: Gain multiplier for vocals (default: 0.7, typical range: 0.5-1.0)
@@ -897,9 +905,9 @@ def create_medley_mcp(
897
  instrumental_path=instrumental_path,
898
  vocals_gain=vocals_gain,
899
  instrumental_gain=instrumental_gain,
900
- compressor="threshold=-18dB:ratio=3:attack=50:release=200", # Professional compression settings
901
  audio_codec="libmp3lame" if output_format == "mp3" else "pcm_s16le",
902
- audio_bitrate="192k" if output_format == "mp3" else "128k",
903
  output_path=None, # Use default temp location
904
  )
905
  return result
@@ -1079,6 +1087,7 @@ def trim_audio_mcp(
1079
  )
1080
  return result
1081
  except Exception as e:
 
1082
  return f"Error trimming audio: {str(e)}"
1083
 
1084
 
@@ -1183,8 +1192,11 @@ def create_interface() -> gr.TabbedInterface:
1183
 
1184
  # Tab 1: Stem Separation
1185
  stem_interface = gr.Interface(
1186
- fn=separate_audio,
1187
- inputs=gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
 
 
 
1188
  outputs=[
1189
  gr.Audio(label="Vocals", type="filepath"),
1190
  gr.Audio(label="Drums", type="filepath"),
@@ -1200,7 +1212,7 @@ def create_interface() -> gr.TabbedInterface:
1200
 
1201
  # Tab 2: Track Combination
1202
  combine_interface = gr.Interface(
1203
- fn=combine_tracks,
1204
  inputs=[
1205
  gr.Audio(type="filepath", label="First Audio Track", sources=["upload"]),
1206
  gr.Audio(type="filepath", label="Second Audio Track", sources=["upload"]),
@@ -1224,10 +1236,11 @@ def create_interface() -> gr.TabbedInterface:
1224
 
1225
  # Tab 3: Pitch Alignment
1226
  pitch_interface = gr.Interface(
1227
- fn=pitch_shift_with_semitones,
1228
  inputs=[
1229
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1230
  gr.Number(value=0, label="Semitones to Shift"),
 
1231
  ],
1232
  outputs=gr.Audio(label="Pitch Shifted Audio", type="filepath"),
1233
  title="Pitch Shift Audio",
@@ -1367,10 +1380,12 @@ def create_interface() -> gr.TabbedInterface:
1367
 
1368
  # Tab 5: BPM Alignment
1369
  bpm_interface = gr.Interface(
1370
- fn=align_songs_by_bpm,
1371
  inputs=[
1372
  gr.Audio(type="filepath", label="First Audio Track", sources=["upload"]),
1373
  gr.Audio(type="filepath", label="Second Audio Track", sources=["upload"]),
 
 
1374
  ],
1375
  outputs=[
1376
  gr.Audio(label="Aligned First Track", type="filepath"),
@@ -1393,7 +1408,12 @@ def create_interface() -> gr.TabbedInterface:
1393
  gr.Checkbox(value=True, label="Extract Bass"),
1394
  gr.Checkbox(value=True, label="Extract Other"),
1395
  ],
1396
- outputs=gr.JSON(label="Extracted Stems"),
 
 
 
 
 
1397
  title="Selective Stem Extraction",
1398
  description="Extract only specific stems from an audio file to save processing time and storage.",
1399
  examples=None,
@@ -1430,27 +1450,21 @@ def create_interface() -> gr.TabbedInterface:
1430
 
1431
  # Tab 9: Medley Creation
1432
  medley_interface = gr.Interface(
1433
- fn=create_medley,
1434
  inputs=[
1435
  gr.Audio(type="filepath", label="Vocals Stem", sources=["upload"]),
1436
  gr.Audio(type="filepath", label="Instrumental Stem", sources=["upload"]),
1437
  gr.Number(
1438
- value=1.2, label="Vocals Gain", minimum=0.1, maximum=3.0, step=0.1
1439
  ),
1440
  gr.Number(
1441
- value=0.9, label="Instrumental Gain", minimum=0.1, maximum=3.0, step=0.1
1442
- ),
1443
- gr.Textbox(
1444
- value="threshold=-18dB:ratio=3:attack=50:release=200",
1445
- label="Compressor Settings",
1446
- placeholder="threshold=-18dB:ratio=3:attack=50:release=200",
1447
  ),
1448
  gr.Dropdown(
1449
- choices=["libmp3lame", "aac", "flac", "pcm_s16le"],
1450
- value="libmp3lame",
1451
- label="Audio Codec",
1452
  ),
1453
- gr.Textbox(value="192k", label="Audio Bitrate", placeholder="192k"),
1454
  ],
1455
  outputs=gr.Audio(label="Medley Audio", type="filepath"),
1456
  title="Create Vocal/Instrumental Medley",
@@ -1462,7 +1476,7 @@ def create_interface() -> gr.TabbedInterface:
1462
 
1463
  # Tab 10: Audio Information
1464
  audio_info_interface = gr.Interface(
1465
- fn=get_audio_info,
1466
  inputs=gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1467
  outputs=gr.JSON(label="Audio Information"),
1468
  title="Get Audio Information",
@@ -1474,7 +1488,7 @@ def create_interface() -> gr.TabbedInterface:
1474
 
1475
  # Tab 11: YouTube Extraction
1476
  youtube_interface = gr.Interface(
1477
- fn=extract_audio_from_youtube,
1478
  inputs=[
1479
  gr.Textbox(
1480
  label="YouTube URL", placeholder="https://www.youtube.com/watch?v=..."
@@ -1510,7 +1524,7 @@ def create_interface() -> gr.TabbedInterface:
1510
 
1511
  # Tab 13: Audio Cutting
1512
  cut_interface = gr.Interface(
1513
- fn=cut_audio,
1514
  inputs=[
1515
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1516
  gr.Number(value=0.0, label="Start Time (seconds)"),
@@ -1558,9 +1572,14 @@ def create_interface() -> gr.TabbedInterface:
1558
  gr.Dropdown(choices=["wav", "mp3"], value="wav", label="Output Format"),
1559
  gr.Checkbox(value=False, label="Join Segments"),
1560
  ],
1561
- outputs=gr.Audio(label="Extracted Segments", type="filepath"),
 
 
 
 
 
1562
  title="Extract Segments",
1563
- description="Extract multiple segments from an audio file.",
1564
  examples=None,
1565
  cache_examples=False,
1566
  flagging_mode="never",
@@ -1568,7 +1587,7 @@ def create_interface() -> gr.TabbedInterface:
1568
 
1569
  # Tab 15: Trim Audio
1570
  trim_interface = gr.Interface(
1571
- fn=trim_audio,
1572
  inputs=[
1573
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1574
  gr.Number(value=None, label="Trim Start (seconds, leave empty to skip)"),
@@ -1637,7 +1656,7 @@ def create_interface() -> gr.TabbedInterface:
1637
 
1638
  # Tab 19: Genre and Style Analysis
1639
  genre_interface = gr.Interface(
1640
- fn=analyze_genre_and_style,
1641
  inputs=[
1642
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1643
  ],
 
112
 
113
  def extract_selected_stems_wrapper(
114
  audio_path: str, vocals: bool, drums: bool, bass: bool, other: bool
115
+ ) -> Tuple[str|None, str|None, str|None, str|None]:
116
  """
117
  Extract selected stems from an audio file based on user choices.
118
 
 
127
  other: Whether to extract the other stem
128
 
129
  Returns:
130
+ tuple[str|None, str|None, str|None, str|None]: Paths to (vocals_file, drums_file, bass_file, other_file)
131
 
132
  Examples:
133
  >>> extract_selected_stems_wrapper("song.wav", True, True, False, False)
 
157
  if not stems_to_extract:
158
  raise ValueError("At least one stem must be selected for extraction")
159
 
160
+ results= extract_selected_stems(audio_path, stems_to_extract)
161
+
162
+ vocals = results.get("vocals")
163
+ drums = results.get("drums")
164
+ bass = results.get("bass")
165
+ other = results.get("other")
166
+
167
+ return vocals, drums, bass, other
168
 
169
 
170
  def extract_vocal_non_vocal_wrapper(audio_path: str) -> Tuple[str, str]:
 
268
 
269
  def extract_segments_wrapper(
270
  audio_path: str, segments_str: str, format_val: str, join: bool
271
+ ) -> Tuple[str, str|None, str|None, str|None]:
272
  """
273
+ Extract multiple segments (up to 4 segments) from an audio file and optionally join them.
274
 
275
  This wrapper function parses JSON-formatted time segments and extracts
276
  the specified portions from the audio file, with an option to join
 
312
  output_format=format_val,
313
  join_segments=join,
314
  )
315
+
316
+ # Handle different return types
317
  if isinstance(result, list):
318
+ # Return list as tuple (pad with empty strings if needed)
319
+ while len(result) < 4:
320
+ result.append(None)
321
+ return result[0], result[1], result[2], result[3]
322
+ else:
323
+ # Return single result as tuple with empty strings
324
+ return result, None, None, None
325
+ except Exception as ex:
326
+ return f"Error: {ex}", None, None, None
327
 
328
 
329
  def analyze_music_structure_wrapper(audio_path: str) -> str:
 
682
  # MCP Tool Wrappers with Documentation for MCP Server
683
 
684
 
685
+ def separate_audio_mcp(audio_path: str, output_format: str = "wav") -> Tuple[str, str, str, str]:
686
  """
687
  Separate audio into vocals, drums, bass, and other stems using Demucs neural network.
688
 
689
+ This MCP tool uses Demucs model to isolate individual instrument stems from a mixed
690
  audio file, providing high-quality separation for music production, remixing, and analysis.
691
 
692
  Args:
 
694
  output_format: Output format for separated stems ('wav' or 'mp3', default: 'wav')
695
 
696
  Returns:
697
+ Tuple of paths to separated audio files in order:
698
+ (vocals_path, drums_path, bass_path, other_path)
 
 
 
 
 
699
 
700
  Examples:
701
  >>> separate_audio_mcp("song.mp3", "wav")
702
+ # Returns ('/tmp/vocals.wav', '/tmp/drums.wav', '/tmp/bass.wav', '/tmp/other.wav')
703
 
704
  Note:
705
  - Processing time varies with audio length and complexity
 
713
  output_path=None, # Use default temp location
714
  output_format=output_format,
715
  )
716
+ return vocals, drums, bass, other
 
 
 
 
 
717
  except Exception as e:
718
+ return f"Error separating audio: {str(e)}", f"Error: {str(e)}", f"Error: {str(e)}", f"Error: {str(e)}"
719
 
720
 
721
  def combine_tracks_mcp(
 
724
  weight1: float = 0.5,
725
  weight2: float = 0.5,
726
  normalize: bool = True,
727
+ fade_in: float = 0.0,
728
+ fade_out: float = 0.0,
729
  output_format: str = "wav",
730
  ) -> str:
731
  """
 
740
  weight1: Mixing weight for track1 (0.0 to 1.0, default: 0.5)
741
  weight2: Mixing weight for track2 (0.0 to 1.0, default: 0.5)
742
  normalize: Whether to normalize the output to prevent clipping (default: True)
743
+ fade_in: Duration in seconds for fade-in at the start of the combined track (default: 0.0)
744
+ fade_out: Duration in seconds for fade-out at the end of the combined track (default: 0.0)
745
  output_format: Output format for combined audio ('wav' or 'mp3', default: 'wav')
746
 
747
  Returns:
748
  Path to the combined audio file
749
 
750
  Examples:
751
+ >>> combine_tracks_mcp("vocals.wav", "instrumental.wav", 0.6, 0.4, True, 0.0, 0.0, "wav")
752
  # Returns 'path/to/combined.wav' with vocals at 60%, instrumental at 40%
753
 
754
+ >>> combine_tracks_mcp("drums.mp3", "bass.mp3", 0.7, 0.3, False, 0.0, 0.0, "mp3")
755
  # Returns 'path/to/combined.mp3' without normalization
756
 
757
  Note:
 
768
  weight2=weight2,
769
  output_path=None, # Use default temp location
770
  normalize=normalize,
771
+ fade_in=fade_in,
772
+ fade_out=fade_out,
773
  output_format=output_format,
774
  )
775
  return result
 
876
  including gain control, compression, and high-quality mixing for polished results.
877
 
878
  Args:
879
+
880
  vocals_path: Path to the vocals audio file or URL (supports common formats: WAV, MP3, FLAC, M4A)
881
  instrumental_path: Path to the instrumental audio file or URL (supports common formats: WAV, MP3, FLAC, M4A)
882
  vocals_gain: Gain multiplier for vocals (default: 0.7, typical range: 0.5-1.0)
 
905
  instrumental_path=instrumental_path,
906
  vocals_gain=vocals_gain,
907
  instrumental_gain=instrumental_gain,
908
+ compressor="threshold=-18dB:ratio=3:attack=50:release=200",
909
  audio_codec="libmp3lame" if output_format == "mp3" else "pcm_s16le",
910
+ audio_bitrate="192k" if output_format == "mp3" else "",
911
  output_path=None, # Use default temp location
912
  )
913
  return result
 
1087
  )
1088
  return result
1089
  except Exception as e:
1090
+ print(e)
1091
  return f"Error trimming audio: {str(e)}"
1092
 
1093
 
 
1192
 
1193
  # Tab 1: Stem Separation
1194
  stem_interface = gr.Interface(
1195
+ fn=separate_audio_mcp,
1196
+ inputs=[
1197
+ gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1198
+ gr.Dropdown(choices=["wav", "mp3"], value="wav", label="Output Format"),
1199
+ ],
1200
  outputs=[
1201
  gr.Audio(label="Vocals", type="filepath"),
1202
  gr.Audio(label="Drums", type="filepath"),
 
1212
 
1213
  # Tab 2: Track Combination
1214
  combine_interface = gr.Interface(
1215
+ fn=combine_tracks_mcp,
1216
  inputs=[
1217
  gr.Audio(type="filepath", label="First Audio Track", sources=["upload"]),
1218
  gr.Audio(type="filepath", label="Second Audio Track", sources=["upload"]),
 
1236
 
1237
  # Tab 3: Pitch Alignment
1238
  pitch_interface = gr.Interface(
1239
+ fn=pitch_shift_with_semitones_mcp,
1240
  inputs=[
1241
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1242
  gr.Number(value=0, label="Semitones to Shift"),
1243
+ gr.Dropdown(choices=["wav", "mp3"], value="wav", label="Output Format"),
1244
  ],
1245
  outputs=gr.Audio(label="Pitch Shifted Audio", type="filepath"),
1246
  title="Pitch Shift Audio",
 
1380
 
1381
  # Tab 5: BPM Alignment
1382
  bpm_interface = gr.Interface(
1383
+ fn=align_songs_by_bpm_mcp,
1384
  inputs=[
1385
  gr.Audio(type="filepath", label="First Audio Track", sources=["upload"]),
1386
  gr.Audio(type="filepath", label="Second Audio Track", sources=["upload"]),
1387
+ gr.Number(value=120.0, label="Target BPM"),
1388
+ gr.Dropdown(choices=["wav", "mp3"], value="wav", label="Output Format"),
1389
  ],
1390
  outputs=[
1391
  gr.Audio(label="Aligned First Track", type="filepath"),
 
1408
  gr.Checkbox(value=True, label="Extract Bass"),
1409
  gr.Checkbox(value=True, label="Extract Other"),
1410
  ],
1411
+ outputs=[
1412
+ gr.Audio(label="Vocals Stem", type="filepath"),
1413
+ gr.Audio(label="Drums Stem", type="filepath"),
1414
+ gr.Audio(label="Bass Stem", type="filepath"),
1415
+ gr.Audio(label="Other Stem", type="filepath"),
1416
+ ],
1417
  title="Selective Stem Extraction",
1418
  description="Extract only specific stems from an audio file to save processing time and storage.",
1419
  examples=None,
 
1450
 
1451
  # Tab 9: Medley Creation
1452
  medley_interface = gr.Interface(
1453
+ fn=create_medley_mcp,
1454
  inputs=[
1455
  gr.Audio(type="filepath", label="Vocals Stem", sources=["upload"]),
1456
  gr.Audio(type="filepath", label="Instrumental Stem", sources=["upload"]),
1457
  gr.Number(
1458
+ value=0.7, label="Vocals Gain", minimum=0.1, maximum=3.0, step=0.1
1459
  ),
1460
  gr.Number(
1461
+ value=0.8, label="Instrumental Gain", minimum=0.1, maximum=3.0, step=0.1
 
 
 
 
 
1462
  ),
1463
  gr.Dropdown(
1464
+ choices=["wav", "mp3"],
1465
+ value="wav",
1466
+ label="Output Format",
1467
  ),
 
1468
  ],
1469
  outputs=gr.Audio(label="Medley Audio", type="filepath"),
1470
  title="Create Vocal/Instrumental Medley",
 
1476
 
1477
  # Tab 10: Audio Information
1478
  audio_info_interface = gr.Interface(
1479
+ fn=get_audio_info_mcp,
1480
  inputs=gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1481
  outputs=gr.JSON(label="Audio Information"),
1482
  title="Get Audio Information",
 
1488
 
1489
  # Tab 11: YouTube Extraction
1490
  youtube_interface = gr.Interface(
1491
+ fn=extract_audio_from_youtube_mcp,
1492
  inputs=[
1493
  gr.Textbox(
1494
  label="YouTube URL", placeholder="https://www.youtube.com/watch?v=..."
 
1524
 
1525
  # Tab 13: Audio Cutting
1526
  cut_interface = gr.Interface(
1527
+ fn=cut_audio_mcp,
1528
  inputs=[
1529
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1530
  gr.Number(value=0.0, label="Start Time (seconds)"),
 
1572
  gr.Dropdown(choices=["wav", "mp3"], value="wav", label="Output Format"),
1573
  gr.Checkbox(value=False, label="Join Segments"),
1574
  ],
1575
+ outputs=[
1576
+ gr.Audio(label="Extracted Segment 1", type="filepath"),
1577
+ gr.Audio(label="Extracted Segment 2", type="filepath"),
1578
+ gr.Audio(label="Extracted Segment 3", type="filepath"),
1579
+ gr.Audio(label="Extracted Segment 4", type="filepath"),
1580
+ ],
1581
  title="Extract Segments",
1582
+ description="Extract multiple segments from an audio file. Shows up to 4 segments (first segment when not joined).",
1583
  examples=None,
1584
  cache_examples=False,
1585
  flagging_mode="never",
 
1587
 
1588
  # Tab 15: Trim Audio
1589
  trim_interface = gr.Interface(
1590
+ fn=trim_audio_mcp,
1591
  inputs=[
1592
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1593
  gr.Number(value=None, label="Trim Start (seconds, leave empty to skip)"),
 
1656
 
1657
  # Tab 19: Genre and Style Analysis
1658
  genre_interface = gr.Interface(
1659
+ fn=analyze_genre_and_style_mcp,
1660
  inputs=[
1661
  gr.Audio(type="filepath", label="Upload Audio File", sources=["upload"]),
1662
  ],