Skip to main content
Glama

generate_prompt_song

Generate songs from text descriptions by providing themes or emotions, with AI creating titles, lyrics, and style. Specify instrumental tracks or music styles as needed.

Instructions

šŸŽ¼ Inspiration Mode: Generate songs based on simple text descriptions (AI automatically generates title, lyrics, style, etc.)

Use case: Use when users only provide simple song themes or emotional descriptions without detailed specifications.

Example inputs:
- "Help me generate a song about a peaceful morning"
- "Want a song that expresses longing"
- "Create music about friendship"

āš ļø COST WARNING: This tool makes an API call to MusicMCP.AI which may incur costs (5 credits per generation). Each generation creates 2 songs. Only use when explicitly requested by the user.

Language Note: Pass the prompt in the user's input language.

Args:
    prompt (str): Song theme or emotional description, 1-1200 characters
    instrumental (bool): Whether instrumental only (no lyrics)
    style (str, optional): Music style (e.g., "ambient", "pop", "rock"), default None

Returns:
    Song information including download URLs

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
promptYes
instrumentalYes
styleNo

Implementation Reference

  • The core handler function implementing the 'generate_prompt_song' tool logic: input validation, API call to create generation task, polling for completion, result formatting and return.
    async def generate_prompt_song(
        prompt: str,
        instrumental: bool,
        style: str | None = None
    ) -> list[TextContent]:
        try:
            if not api_key:
                raise Exception("Cannot find API key. Please set MUSICMCP_API_KEY environment variable.")
    
            if not prompt or prompt.strip() == "":
                raise Exception("Prompt text is required.")
    
            if len(prompt.strip()) > 1200:
                raise Exception("Prompt text must be less than 1200 characters.")
    
            url = f"{api_url}/music/generate/inspiration"
            headers = {
                'api-key': api_key,
                'Content-Type': 'application/json'
            }
    
            params = {
                "prompt": prompt,
                "instrumental": instrumental,
            }
    
            if style is not None:
                params["style"] = style
    
            async with httpx.AsyncClient(timeout=httpx.Timeout(60.0)) as client:
                response = await client.post(url, json=params, headers=headers)
                response.raise_for_status()
                result = response.json()
    
            # API response format: {success, message, data}
            if not result or not result.get("success"):
                error_msg = result.get("message", "Unknown error") if result else "No response"
                raise Exception(f"Failed to create song generation task: {error_msg}")
    
            # Format: data contains {ids: [...]}
            data = result.get("data", {})
            song_ids = data.get("ids", [])
    
            if not song_ids:
                raise Exception("No song IDs returned from API")
    
            # Redirect debug info to stderr to avoid breaking JSON-RPC
            print(f"āœ… Song generation task created. Song IDs: {song_ids}", file=sys.stderr)
    
            # Poll for task completion
            current_timestamp = datetime.now().timestamp()
            while True:
                if (datetime.now().timestamp() - current_timestamp) > default_time_out:
                    raise Exception(f"Song generation timed out after {default_time_out} seconds")
    
                songs, status = await query_song_task(song_ids)
    
                if status == "error":
                    raise Exception("Song generation failed with error status")
                elif status == "timeout":
                    raise Exception("Song generation timed out")
                elif status == "completed" or status == "success":
                    break
                else:
                    time.sleep(2)
    
            # Return song information with URLs
            results = []
            for i, song in enumerate(songs, 1):
                song_url = song.get("songUrl") or song.get("audio_url") or song.get("url")
                song_title = song.get("songName", f"Song {i}").strip()
                song_id = song.get("id", "N/A")
    
                # Additional fields
                duration = song.get("duration", 0)
                tags = song.get("tags", "")
                img_url = song.get("imgUrl", "")
                lyric = song.get("lyric", "")
                instrumental = song.get("instrumental", 0)
                created_at = song.get("createdAt", "")
    
                if not song_url:
                    continue
    
                # Format duration
                duration_str = f"{duration}s" if duration else "N/A"
    
                # Format instrumental status
                is_instrumental = "Yes" if instrumental == 1 else "No"
    
                text = f"""āœ… Song {i} generated successfully!
    
    šŸ“Œ Title: {song_title}
    šŸ†” ID: {song_id}
    šŸ”— Download URL: {song_url}
    šŸ–¼ļø  Cover Image: {img_url if img_url else "N/A"}
    ā±ļø  Duration: {duration_str}
    šŸŽµ Style Tags: {tags if tags else "N/A"}
    šŸŽ¹ Instrumental: {is_instrumental}
    šŸ“… Created: {created_at if created_at else "N/A"}"""
    
                # Add lyrics if available and not instrumental
                if lyric and instrumental == 0:
                    text += f"\nšŸ“ Lyrics:\n{lyric}"
    
                text += "\n\nYou can download or play the audio from the URL above."
    
                results.append(TextContent(type="text", text=text))
    
            if not results:
                raise Exception("No songs were generated successfully")
    
            return results
    
        except httpx.HTTPStatusError as e:
            error_detail = f"HTTP {e.response.status_code}"
            if e.response.status_code == 402:
                error_detail = "Insufficient credits. Please recharge your account."
            elif e.response.status_code == 401:
                error_detail = "Invalid API key. Please check your MUSICMCP_API_KEY."
            raise Exception(f"Request failed: {error_detail}") from e
        except Exception as e:
            raise Exception(f"Song generation failed: {str(e)}") from e
  • Tool registration via @mcp.tool decorator on FastMCP instance, including schema description for inputs and usage instructions.
    @mcp.tool(
        description="""šŸŽ¼ Inspiration Mode: Generate songs based on simple text descriptions (AI automatically generates title, lyrics, style, etc.)
    
        Use case: Use when users only provide simple song themes or emotional descriptions without detailed specifications.
    
        Example inputs:
        - "Help me generate a song about a peaceful morning"
        - "Want a song that expresses longing"
        - "Create music about friendship"
    
        āš ļø COST WARNING: This tool makes an API call to MusicMCP.AI which may incur costs (5 credits per generation). Each generation creates 2 songs. Only use when explicitly requested by the user.
    
        Language Note: Pass the prompt in the user's input language.
    
        Args:
            prompt (str): Song theme or emotional description, 1-1200 characters
            instrumental (bool): Whether instrumental only (no lyrics)
            style (str, optional): Music style (e.g., "ambient", "pop", "rock"), default None
    
        Returns:
            Song information including download URLs
        """
    )
  • Supporting helper function used by generate_prompt_song to poll the API for song generation task status and completion.
    async def query_song_task(song_ids: list[str]) -> tuple[list, str]:
        """Query song generation task status
    
        Args:
            song_ids: List of song IDs (batch query supported)
    
        Returns:
            Tuple of (songs_list, status_string)
        """
        try:
            url = f"{api_url}/music/generate/query"
            headers = {
                'api-key': api_key,
                'Content-Type': 'application/json'
            }
            params = {"ids": song_ids}
    
            async with httpx.AsyncClient(timeout=httpx.Timeout(60.0)) as client:
                response = await client.post(url, json=params, headers=headers)
                response.raise_for_status()
                result = response.json()
    
            # API response format: {success, message, data}
            if not result or not result.get("success"):
                return [], "error"
    
            # Format: data contains {songs: [...]}
            data = result.get("data", {})
            songs = data.get("songs", [])
    
            if songs and len(songs) > 0:
                all_complete = True
                any_error = False
    
                for song in songs:
                    status = song.get("status", 0)
                    if status == 0:  # 0 = Failed
                        any_error = True
                        break
                    elif status != 1:  # 1 = Completed, 2 = In Progress
                        all_complete = False
    
                if any_error:
                    return songs, "error"
                elif all_complete:
                    return songs, "completed"
                else:
                    return songs, "processing"
            else:
                return [], "processing"
    
        except Exception as e:
            # Redirect error info to stderr to avoid breaking JSON-RPC
            print(f"Query error: {str(e)}", file=sys.stderr)
            raise Exception(f"Failed to query song status: {str(e)}") from e

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/amCharlie/aimusic-mcp-tool'

If you have feedback or need assistance with the MCP directory API, please join our Discord server