File size: 4,209 Bytes
9a9156e
2e8b534
 
9a9156e
 
 
3e4b08a
bcfd645
3e4b08a
9a9156e
 
3e4b08a
 
9a9156e
 
 
 
 
 
bcfd645
 
 
 
 
8eff04a
 
bcfd645
 
8eff04a
2e8b534
 
 
 
 
 
9a9156e
 
2e8b534
 
 
 
9a9156e
 
2e8b534
9a9156e
 
 
2e8b534
9a9156e
2e8b534
9a9156e
 
132d45b
8eff04a
132d45b
 
 
 
 
 
 
 
 
 
9a9156e
132d45b
 
9a9156e
 
2e8b534
 
 
9a9156e
 
2e8b534
9a9156e
 
 
2e8b534
9a9156e
2e8b534
9a9156e
 
132d45b
8eff04a
9a9156e
 
132d45b
 
 
 
 
 
 
 
9a9156e
132d45b
 
9a9156e
 
2e8b534
 
9a9156e
bcfd645
 
 
 
 
 
 
 
 
 
 
 
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
# hf_spaces_mcp_server.py
from mcp.server.fastmcp import FastMCP
from gradio_client import Client
import os
import sys
import asyncio
import logging
import uvicorn # Correctly imported

# Configure basic logging to see server activity
logging.basicConfig(level=logging.INFO, stream=sys.stdout)
logger = logging.getLogger(__name__)

# The port that Hugging Face Spaces expects our app to listen on.
# It injects this as an environment variable 'PORT'.
# Default to 7860 if PORT is not set (e.g., for local testing outside HF Spaces).
HOST_PORT = int(os.getenv("PORT", 7860))
HOST_ADDRESS = os.getenv("HOST", "0.0.0.0") # Bind to all interfaces

# Initialize FastMCP. The host/port settings passed here will be used by
# mcp.streamable_http_app() to configure its internal server if not mounted to FastAPI.
# However, when passed to uvicorn.run(), uvicorn's host/port will take precedence.
# It's good practice to keep them consistent or omit from here if uvicorn dictates.
# For simplicity, we'll keep them here as they are also part of MCP server's self-description.
mcp = FastMCP(
    name="GradioSpacesTools",
    host=HOST_ADDRESS,
    port=HOST_PORT
)

clients = {}

def get_client(space_id: str) -> Client:
    """Get or create a Gradio client for the specified space."""
    if space_id not in clients:
        logger.info(f"Creating Gradio client for Space ID: {space_id}")
        clients[space_id] = Client(space_id)
    return clients[space_id]

@mcp.tool()
async def generate_image(prompt: str, space_id: str = "ysharma/SanaSprint") -> str:
    """Generate an image using Flux.
    
    Args:
        prompt (str): Text prompt describing the image to generate
        space_id (str): HuggingFace Space ID to use 
    
    Returns:
        str: The URL of the generated image.
    """
    logger.info(f"Generating image for prompt: '{prompt}' using Space: '{space_id}'")
    client = get_client(space_id)
    try:
        result = await client.predict(
            prompt=prompt,
            model_size="1.6B",
            seed=0,
            randomize_seed=True,
            width=1024,
            height=1024,
            guidance_scale=4.5,
            num_inference_steps=2,
            api_name="/infer"
        )
        logger.info(f"Image generation successful. Result: {result}")
        return result
    except Exception as e:
        logger.error(f"Error generating image: {e}")
        return f"Error generating image: {e}"

@mcp.tool()
async def run_dia_tts(prompt: str, space_id: str = "ysharma/Dia-1.6B") -> str:
    """Text-to-Speech Synthesis.
    
    Args:
        prompt (str): Text prompt describing the conversation between speakers S1, S2
        space_id (str): HuggingFace Space ID to use 
    
    Returns:
        str: The URL of the generated audio.
    """
    logger.info(f"Performing TTS for prompt: '{prompt}' using Space: '{space_id}'")
    client = get_client(space_id)
    try:
        result = await client.predict(
            text_input=f"""{prompt}""",
            audio_prompt_input=None, 
            max_new_tokens=3072,
            cfg_scale=3,
            temperature=1.3,
            top_p=0.95,
            cfg_filter_top_k=30,
            speed_factor=0.94,
            api_name="/generate_audio"
        )
        logger.info(f"TTS successful. Result: {result}")
        return result
    except Exception as e:
        logger.error(f"Error performing TTS: {e}")
        return f"Error performing TTS: {e}"

if __name__ == "__main__":
    sys.stdout = os.fdopen(sys.stdout.fileno(), 'w', 1)
    logger.info(f"Starting GradioSpacesTools MCP server via Uvicorn on http://{HOST_ADDRESS}:{HOST_PORT}")
    
    # The correct way to get the FastMCP ASGI application for streamable-http
    # as indicated by the article and FastMCP's internal structure.
    # Uvicorn will then run this ASGI application.
    uvicorn.run(
        mcp.streamable_http_app(), # <-- Use this method! It returns the ASGI app.
        host=HOST_ADDRESS,
        port=HOST_PORT,
        log_level="info", # Set logging level for Uvicorn itself
        loop="asyncio"    # Ensure Uvicorn uses the asyncio event loop
    )
    logger.info("GradioSpacesTools MCP server stopped.")