|
|
|
|
|
import modal |
|
from contextlib import asynccontextmanager |
|
from fastapi import FastAPI |
|
from gradio.routes import mount_gradio_app |
|
import os |
|
from dotenv import load_dotenv |
|
import uvicorn |
|
from mcp.server.fastmcp import FastMCP |
|
|
|
|
|
from .tools import mcp_tools |
|
from .ui.gradio_ui import create_gradio_interface |
|
from .config.config import is_modal_mode, is_local_mode |
|
|
|
|
|
try: |
|
from .config.modal_config import app, image, volume, cache_dir, secrets |
|
_modal_available = True |
|
except ImportError: |
|
_modal_available = False |
|
|
|
|
|
|
|
def create_app(): |
|
"""Create and return Gradio application with MCP tools integrated""" |
|
|
|
print("π Starting Gradio + FastMCP server") |
|
|
|
|
|
mcp = FastMCP("Podcast MCP") |
|
|
|
|
|
@mcp.tool(description="Transcribe audio files to text using Whisper model with speaker diarization support") |
|
async def transcribe_audio_file_tool( |
|
audio_file_path: str, |
|
model_size: str = "turbo", |
|
language: str = None, |
|
output_format: str = "srt", |
|
enable_speaker_diarization: bool = False |
|
): |
|
return await mcp_tools.transcribe_audio_file( |
|
audio_file_path, model_size, language, output_format, enable_speaker_diarization |
|
) |
|
|
|
@mcp.tool(description="Download Apple Podcast audio files") |
|
async def download_apple_podcast_tool(url: str): |
|
return await mcp_tools.download_apple_podcast(url) |
|
|
|
@mcp.tool(description="Download XiaoYuZhou podcast audio files") |
|
async def download_xyz_podcast_tool(url: str): |
|
return await mcp_tools.download_xyz_podcast(url) |
|
|
|
@mcp.tool(description="Scan directory for MP3 audio files") |
|
async def get_mp3_files_tool(directory: str): |
|
return await mcp_tools.get_mp3_files(directory) |
|
|
|
@mcp.tool(description="Get basic file information") |
|
async def get_file_info_tool(file_path: str): |
|
return await mcp_tools.get_file_info(file_path) |
|
|
|
@mcp.tool(description="Read text file content in segments") |
|
async def read_text_file_segments_tool( |
|
file_path: str, |
|
chunk_size: int = 65536, |
|
start_position: int = 0 |
|
): |
|
return await mcp_tools.read_text_file_segments(file_path, chunk_size, start_position) |
|
|
|
|
|
print("π¨ Creating Gradio interface...") |
|
gradio_app = create_gradio_interface() |
|
|
|
|
|
if os.environ.get("HF_SPACES_MODE") == "1": |
|
print("π€ HF Spaces mode: returning Gradio app directly") |
|
print("β
Server startup completed") |
|
print("π¨ Gradio UI: /") |
|
print(f"π Server name: {mcp.name}") |
|
return gradio_app |
|
|
|
|
|
print("π§ Creating FastAPI wrapper...") |
|
fastapi_wrapper = FastAPI( |
|
title="Modal AudioTranscriber MCP", |
|
description="Gradio UI + FastMCP Tool + Modal Integration AudioTranscriber MCP", |
|
version="1.0.0", |
|
lifespan=lambda app: mcp.session_manager.run() |
|
) |
|
|
|
|
|
mcp_app = mcp.streamable_http_app() |
|
|
|
|
|
fastapi_wrapper.mount("/api", mcp_app) |
|
|
|
|
|
final_app = mount_gradio_app( |
|
app=fastapi_wrapper, |
|
blocks=gradio_app, |
|
path="", |
|
app_kwargs={ |
|
"docs_url": "/docs", |
|
"redoc_url": "/redoc", |
|
} |
|
) |
|
|
|
print("β
Server startup completed") |
|
print("π¨ Gradio UI: /") |
|
print("π§ MCP Streamable HTTP: /api/mcp") |
|
print(f"π Server name: {mcp.name}") |
|
|
|
return final_app |
|
|
|
|
|
|
|
|
|
if _modal_available: |
|
gradio_mcp_app = modal.App(name="gradio-mcp-ui") |
|
|
|
@gradio_mcp_app.function( |
|
image=image, |
|
cpu=2, |
|
memory=4096, |
|
max_containers=5, |
|
min_containers=1, |
|
scaledown_window=600, |
|
timeout=1800, |
|
volumes={cache_dir: volume}, |
|
secrets=secrets, |
|
) |
|
@modal.concurrent(max_inputs=100) |
|
@modal.asgi_app() |
|
def app_entry(): |
|
"""Modal deployment function - create and return complete Gradio + MCP application""" |
|
return create_app() |
|
|
|
|
|
|
|
def run_local(): |
|
"""Run local server with uvicorn""" |
|
print("π Starting in local mode") |
|
|
|
|
|
os.environ.setdefault("DEPLOYMENT_MODE", "local") |
|
|
|
app = create_app() |
|
|
|
|
|
port = int(os.environ.get("PORT", 7860)) |
|
|
|
print(f"π Starting server on port {port}") |
|
|
|
|
|
if os.environ.get("HF_SPACES_MODE") == "1" and hasattr(app, 'launch'): |
|
print("π€ Launching Gradio app for HF Spaces") |
|
app.launch( |
|
server_name="0.0.0.0", |
|
server_port=port, |
|
share=False, |
|
show_error=True |
|
) |
|
else: |
|
|
|
uvicorn.run( |
|
app, |
|
host="0.0.0.0", |
|
port=port, |
|
reload=False |
|
) |
|
|
|
if __name__ == "__main__": |
|
run_local() |