generate_slide_by_slide
Define slides with custom titles, layouts, and content to generate a PowerPoint presentation. Returns a task ID to poll for completion.
Instructions
Generate a PowerPoint presentation using Slide-by-Slide input.
Returns a task_id that can be used with getTaskStatus to check progress.
IMPORTANT: This tool returns immediately with a task_id. You MUST then call
getTaskStatus with the task_id to poll for completion. Keep polling every few
seconds until the status is SUCCESS or FAILED.
Parameters
- template (string): The name of the template or the ID of a custom template.
- language (string, optional): Language code like 'ENGLISH' or 'ORIGINAL'.
- fetch_images (bool, optional): Include stock images (default: True).
- slides (list[dict]): A list of slides, each defined as a dictionary with the following keys:
- title (string): The title of the slide.
- layout (string): The layout type for the slide. See available layout options below.
- item_amount (integer): Number of items for the slide (must match the layout constraints).
- content (string): The content that will be used for the slide.
Available Layouts
- items: 1-5 items
- steps: 3-5 items
- summary: 1-5 items
- comparison: exactly 2 items
- big-number: 1-5 items
- milestone: 3-5 items
- pestel: exactly 6 items
- swot: exactly 4 items
- pyramid: 1-5 items
- timeline: 3-5 items
- funnel: 3-5 items
- quote: 1 item
- cycle: 3-5 items
- thanks: 0 items
Returns
- A string with the task_id and instructions to poll for status.Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| template | Yes | ||
| slides | Yes | ||
| language | No | ||
| fetch_images | No |
Implementation Reference
- slidespeak.py:256-333 (handler)The `generate_slide_by_slide` tool handler. It receives a template name, list of slides, optional language and fetch_images flag, builds a payload, calls the POST /presentation/generate/slide-by-slide API endpoint, and returns a task_id with instructions to poll for completion.
@mcp.tool() async def generate_slide_by_slide( template: str, slides: list[dict[str, Any]], language: Optional[str] = None, fetch_images: Optional[bool] = True, ) -> str: """ Generate a PowerPoint presentation using Slide-by-Slide input. Returns a task_id that can be used with getTaskStatus to check progress. IMPORTANT: This tool returns immediately with a task_id. You MUST then call getTaskStatus with the task_id to poll for completion. Keep polling every few seconds until the status is SUCCESS or FAILED. Parameters - template (string): The name of the template or the ID of a custom template. - language (string, optional): Language code like 'ENGLISH' or 'ORIGINAL'. - fetch_images (bool, optional): Include stock images (default: True). - slides (list[dict]): A list of slides, each defined as a dictionary with the following keys: - title (string): The title of the slide. - layout (string): The layout type for the slide. See available layout options below. - item_amount (integer): Number of items for the slide (must match the layout constraints). - content (string): The content that will be used for the slide. Available Layouts - items: 1-5 items - steps: 3-5 items - summary: 1-5 items - comparison: exactly 2 items - big-number: 1-5 items - milestone: 3-5 items - pestel: exactly 6 items - swot: exactly 4 items - pyramid: 1-5 items - timeline: 3-5 items - funnel: 3-5 items - quote: 1 item - cycle: 3-5 items - thanks: 0 items Returns - A string with the task_id and instructions to poll for status. """ endpoint = "/presentation/generate/slide-by-slide" if not API_KEY: return "API Key is missing. Cannot process any requests." if not isinstance(slides, list) or len(slides) == 0: return "Parameter 'slides' must be a non-empty list of slide objects." payload: dict[str, Any] = { "template": template, "slides": slides, } if language: payload["language"] = language if fetch_images is not None: payload["fetch_images"] = fetch_images # Initiate generation — returns immediately with task_id init_result = await _make_api_request("POST", endpoint, payload=payload, timeout=GENERATION_TIMEOUT) if not init_result: return "Failed to initiate slide-by-slide generation due to an API error. Check server logs." task_id = init_result.get("task_id") if not task_id: return f"Failed to initiate slide-by-slide generation. API response did not contain a task ID. Response: {init_result}" logging.info(f"Slide-by-slide generation initiated. Task ID: {task_id}") return ( f"Generation started. Task ID: {task_id}\n\n" f"The presentation is being generated. Use getTaskStatus with task_id '{task_id}' " f"to check progress. Poll every few seconds until status is SUCCESS.\n" f"Once complete, use downloadPresentation with the request_id from the task result." ) - slidespeak.py:256-256 (registration)The tool is registered via the `@mcp.tool()` decorator from FastMCP, which automatically registers `generate_slide_by_slide` as an MCP tool.
@mcp.tool() - slidespeak.py:257-261 (schema)Input schema/type hints for the tool: template (str), slides (list[dict[str, Any]]), language (Optional[str]), fetch_images (Optional[bool]).
async def generate_slide_by_slide( template: str, slides: list[dict[str, Any]], language: Optional[str] = None, fetch_images: Optional[bool] = True, - slidespeak.py:28-78 (helper)The `_make_api_request` helper function used by the handler to make HTTP requests to the SlideSpeak API.
async def _make_api_request( method: Literal["GET", "POST"], endpoint: str, payload: Optional[dict[str, Any]] = None, timeout: float = DEFAULT_TIMEOUT ) -> Optional[dict[str, Any]]: """ Makes an HTTP request to the SlideSpeak API. Args: method: HTTP method ('GET' or 'POST'). endpoint: API endpoint path (e.g., '/presentation/templates'). payload: JSON payload for POST requests. Ignored for GET. timeout: Request timeout in seconds. Returns: The parsed JSON response as a dictionary on success, None on failure. """ if not API_KEY: logging.error("API Key is missing. Cannot make API request.") return None headers = { "User-Agent": USER_AGENT, "Accept": "application/json", "X-API-Key": API_KEY, } url = f"{API_BASE}{endpoint}" req_start = time.time() async with httpx.AsyncClient() as client: try: if method == "POST": response = await client.post(url, json=payload, headers=headers, timeout=timeout) else: response = await client.get(url, headers=headers, timeout=timeout) elapsed = time.time() - req_start logging.info(f"{method} {url} | status={response.status_code} | elapsed={elapsed:.2f}s") response.raise_for_status() return response.json() except httpx.HTTPStatusError as e: logging.error(f"HTTP error {method} {url}: {e.response.status_code} - {e.response.text}") except httpx.RequestError as e: logging.error(f"Request error {method} {url}: {str(e)}") except Exception as e: logging.error(f"Unexpected error {method} {url}: {str(e)}") return None