Skip to main content
Glama
tripo_api.py7.94 kB
import os import httpx from typing import Dict, Any from dotenv import load_dotenv from models import ( TextToModelRequest, ImageToModelRequest, MultiviewToModelRequest, TextureModelRequest, RefineModelRequest, AnimatePrerigcheckRequest, AnimateRigRequest, AnimateRetargetRequest, StylizeModelRequest, ConvertModelRequest, TaskIdRequest, UploadImageRequest ) load_dotenv() TRIPO_API_KEY = os.getenv("TRIPO_API_KEY") BASE_URL = "https://api.tripo3d.ai/v2/openapi" HEADERS = {"Authorization": f"Bearer {TRIPO_API_KEY}"} async def text_to_model(data: TextToModelRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "text_to_model" async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def image_to_model(data: ImageToModelRequest) -> Dict[str, Any]: # 互斥校验:file_path、file_token、url、object 只能有一个 input_count = sum([bool(data.file_path), bool(data.file_token), bool(data.url), bool(data.object)]) if input_count != 1: return {"code": 2003, "msg": "Exactly one of file_path, file_token, url, object must be provided."} payload = data.model_dump(exclude_none=True) payload["type"] = "image_to_model" # 本地文件优先,且必须真实存在 if data.file_path and os.path.isfile(data.file_path): async with httpx.AsyncClient() as client: with open(data.file_path, "rb") as f: files = {"file": (os.path.basename(data.file_path), f, f"image/{data.file_type or 'jpeg'}")} upload_resp = await client.post(f"{BASE_URL}/upload", headers=HEADERS, files=files) upload_data = upload_resp.json() file_token = upload_data.get("data", {}).get("image_token") payload["file"] = {"type": data.file_type or "jpeg", "file_token": file_token} payload.pop("file_path", None) payload.pop("file_type", None) payload.pop("url", None) payload.pop("object", None) elif data.file_token: payload["file"] = {"type": data.file_type or "jpeg", "file_token": data.file_token} payload.pop("file_path", None) payload.pop("file_type", None) payload.pop("url", None) payload.pop("object", None) elif data.url: payload["file"] = {"type": data.file_type or "jpeg", "url": data.url} payload.pop("file_path", None) payload.pop("file_type", None) payload.pop("file_token", None) payload.pop("object", None) elif data.object: payload["file"] = {"type": data.file_type or "jpeg", "object": data.object} payload.pop("file_path", None) payload.pop("file_type", None) payload.pop("file_token", None) payload.pop("url", None) async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def multiview_to_model(data: MultiviewToModelRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "multiview_to_model" async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def texture_model(data: TextureModelRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "texture_model" async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def refine_model(data: RefineModelRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "refine_model" async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def animate_prerigcheck(data: AnimatePrerigcheckRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "animate_prerigcheck" async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def animate_rig(data: AnimateRigRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "animate_rig" if "out_format" in payload and payload["out_format"] not in ["glb", "fbx"]: return {"code": 2002, "msg": "The out_format is unsupported."} async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def animate_retarget(data: AnimateRetargetRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "animate_retarget" if "out_format" in payload and payload["out_format"] not in ["glb", "fbx"]: return {"code": 2002, "msg": "The out_format is unsupported."} valid_animations = [ "preset:idle", "preset:walk", "preset:climb", "preset:jump", "preset:run", "preset:slash", "preset:shoot", "preset:hurt", "preset:fall", "preset:turn" ] if payload.get("animation") not in valid_animations: return {"code": 2002, "msg": "The animation is unsupported."} async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def stylize_model(data: StylizeModelRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "stylize_model" if payload.get("style") not in ["lego", "voxel", "voronoi", "minecraft"]: return {"code": 2002, "msg": "The style is unsupported."} async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def convert_model(data: ConvertModelRequest) -> Dict[str, Any]: payload = data.model_dump(exclude_none=True) payload["type"] = "convert_model" if payload.get("format") not in ["GLTF", "USDZ", "FBX", "OBJ", "STL", "3MF"]: return {"code": 2002, "msg": "The format is unsupported."} async with httpx.AsyncClient() as client: resp = await client.post(f"{BASE_URL}/task", headers=HEADERS, json=payload) return resp.json() async def get_task_status(data: TaskIdRequest) -> Dict[str, Any]: async with httpx.AsyncClient() as client: resp = await client.get(f"{BASE_URL}/task/{data.task_id}", headers=HEADERS) return resp.json() async def upload_image(data: UploadImageRequest) -> Dict[str, Any]: async with httpx.AsyncClient() as client: with open(data.file_path, "rb") as f: files = {"file": (os.path.basename(data.file_path), f, "image/jpeg")} resp = await client.post(f"{BASE_URL}/upload", headers=HEADERS, files=files) return resp.json() async def get_balance() -> Dict[str, Any]: async with httpx.AsyncClient() as client: try: resp = await client.get(f"{BASE_URL}/user/balance", headers=HEADERS) result = resp.json() if resp.status_code == 200 and isinstance(result, dict): if "code" in result and "data" in result: return result elif "balance" in result and "frozen" in result: return {"code": 0, "data": {"balance": result["balance"], "frozen": result["frozen"]}} else: return {"code": 0, "data": result} else: return {"code": 1001, "msg": "Fatal error on server side", "http_status": resp.status_code} except Exception as e: return {"code": 1001, "msg": f"Fatal error: {str(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/lxy2109/tripo-mcp'

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