WM StudioDocs
ToolsWorkflowsChangelogGitHub
  • Introduction
  • Getting started
  • Configuration
  • Tool index
  • Workflows
  • Examples
  • Errors
  • Changelog
Snippets

Examples

Copy-ready clients for the Streamable HTTP transport.

TypeScript client

client.ts
import { Client } from "@modelcontextprotocol/sdk/client/index.js"
import { StreamableHTTPClientTransport } from "@modelcontextprotocol/sdk/client/streamableHttp.js"

const transport = new StreamableHTTPClientTransport(
  new URL(`${process.env.MCP_BASE_URL}/mcp/`),
  { requestInit: { headers: { Authorization: `Bearer ${process.env.MCP_JWT}` } } },
)

const client = new Client({ name: "wm-studio", version: "1.0.0" }, { capabilities: {} })
await client.connect(transport)

const tools = await client.listTools()
console.log(tools.tools.map((t) => t.name))

const result = await client.callTool({
  name: "studio_generate_image",
  arguments: {
    prompt: "minimalist product photo of a black ceramic mug",
    model: "fal-ai/flux-2-pro",
    aspect_ratio: "4:3",
  },
})
console.log(result)

Python client

client.py
from mcp import ClientSession
from mcp.client.streamable_http import streamablehttp_client

import os

async def main():
    url = f"{os.environ['MCP_BASE_URL']}/mcp/"
    headers = {"Authorization": f"Bearer {os.environ['MCP_JWT']}"}
    async with streamablehttp_client(url, headers=headers) as (read, write, _):
        async with ClientSession(read, write) as session:
            await session.initialize()
            tools = await session.list_tools()
            print([t.name for t in tools.tools])
            result = await session.call_tool("studio_generate_image", {
                "prompt": "minimalist product photo of a black ceramic mug",
                "model": "fal-ai/flux-2-pro",
            })
            print(result)

import asyncio
asyncio.run(main())

Raw curl

Plain JSON-RPC over Streamable HTTP. Useful for smoke tests in CI.

bash
curl -X POST "$MCP_BASE_URL/mcp/" \
  -H "Authorization: Bearer $MCP_JWT" \
  -H "Content-Type: application/json" \
  -H "Accept: application/json, text/event-stream" \
  -d '{
    "jsonrpc": "2.0",
    "id": 1,
    "method": "tools/call",
    "params": {
      "name": "studio_upscale_image",
      "arguments": {
        "image_url": "https://cdn.wm.studio/uploads/portrait.jpg",
        "scale": 4
      }
    }
  }'

Async polling

Long-running tools (studio_generate_video, studio_digital_twin,studio_convert_to_3d) return a job_id immediately. Poll untilstatus is completed or failed.

ts
async function generateVideoAndWait(prompt: string, imageUrl: string) {
  const start = await client.callTool({
    name: "studio_generate_video",
    arguments: {
      prompt,
      image_url: imageUrl,
      model: "fal-ai/kling-video/v2.5-turbo/pro/image-to-video",
    },
  }) as { job_id: string }

  for (let i = 0; i < 120; i++) {
    const status = await client.callTool({
      name: "studio_job_status",
      arguments: { job_id: start.job_id },
    }) as { status: string; video?: { url: string } }

    if (status.status === "completed") return status.video?.url
    if (status.status === "failed") throw new Error("video render failed")
    await new Promise((r) => setTimeout(r, 5000))
  }
  throw new Error("timed out")
}
On this page
  • TypeScript client
  • Python client
  • Raw curl
  • Async polling
WM Studio MCP — v2.0.0
Docs home