tiktok_publish
Publish videos to TikTok using automated browser sessions. Upload video files, add captions, and include hashtags through authenticated Creator Center access.
Instructions
Publish a video to TikTok. Requires authenticated session. Uses browser automation via Creator Center.
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| video_path | Yes | Path to the video file to upload | |
| caption | Yes | Video caption/description | |
| hashtags | No | List of hashtags (without #) |
Implementation Reference
- tiktok_mcp/browser.py:659-790 (handler)The publish_video method uses Playwright to navigate to the TikTok Creator Center, upload the specified video file, add a caption and hashtags, and click the post button.
async def publish_video( self, video_path: str, caption: str, hashtags: list[str] = None, ) -> dict: """Publish a video to TikTok via Creator Center.""" result = {"success": False} if not os.path.exists(video_path): result["error"] = f"Video file not found: {video_path}" return result try: page = await self.goto_tiktok("/creator-center/upload") await asyncio.sleep(5) # Check if redirected to login if "login" in page.url: result["error"] = "Not authenticated. Run tiktok_session with action=check_login first." return result # Find file input and upload file_input = await page.query_selector('input[type="file"]') if not file_input: # Sometimes hidden, try to find it file_input = await page.wait_for_selector('input[type="file"]', timeout=15000) if not file_input: result["error"] = "Could not find upload input" return result await file_input.set_input_files(os.path.abspath(video_path)) logger.info(f"Uploaded video file: {video_path}") # Wait for processing await asyncio.sleep(15) # Find caption/description field caption_field = await page.query_selector('div[contenteditable="true"]') if not caption_field: caption_field = await page.wait_for_selector( 'div[contenteditable="true"]', timeout=20000 ) if caption_field: # Clear existing text await caption_field.click() await page.keyboard.press("Control+a") await page.keyboard.press("Backspace") await asyncio.sleep(0.5) # Type caption await caption_field.type(caption, delay=random.randint(20, 50)) # Add hashtags if hashtags: await caption_field.type("\n\n", delay=50) hashtag_text = " ".join(f"#{tag.lstrip('#')}" for tag in hashtags) await caption_field.type(hashtag_text, delay=random.randint(20, 50)) await asyncio.sleep(3) # Dismiss tutorial overlay if present try: overlay = await page.query_selector('[class*="joyride"], [class*="overlay"]') if overlay: await overlay.click() await asyncio.sleep(1) except: pass # Click Post button post_selectors = [ 'button:has-text("Post")', 'button:has-text("Publier")', '[data-e2e="post"]', 'button[class*="submit"]', ] post_btn = None for sel in post_selectors: try: post_btn = await page.query_selector(sel) if post_btn and await post_btn.is_visible() and await post_btn.is_enabled(): break post_btn = None except: continue if not post_btn: result["error"] = "Could not find Post button" return result await post_btn.click() await asyncio.sleep(5) # Handle "Continue to post?" dialog for _ in range(12): try: post_now = await page.query_selector( 'button:has-text("Post now"), button:has-text("Publier maintenant")' ) if post_now and await post_now.is_visible(): await post_now.click() await asyncio.sleep(3) except: pass # Check for success if "/content" in page.url: result["success"] = True result["message"] = "Video published successfully" return result # Check for success message success_el = await page.query_selector( ':has-text("Your video is"), :has-text("being uploaded")' ) if success_el: result["success"] = True result["message"] = "Video upload in progress" return result await asyncio.sleep(10) result["error"] = "Publish timed out — no confirmation received" except Exception as e: result["error"] = str(e) return result - tiktok_mcp/server.py:266-272 (handler)The server-side handler that receives the 'tiktok_publish' tool call and executes the browser.publish_video() method.
elif name == "tiktok_publish": result = await browser.publish_video( arguments["video_path"], arguments["caption"], arguments.get("hashtags", []), ) return [TextContent(type="text", text=json.dumps(result, indent=2, ensure_ascii=False))] - tiktok_mcp/server.py:132-148 (registration)Definition of the 'tiktok_publish' tool in the TOOLS list, including input schema.
Tool( name="tiktok_publish", description="Publish a video to TikTok. Requires authenticated session. Uses browser automation via Creator Center.", inputSchema={ "type": "object", "properties": { "video_path": {"type": "string", "description": "Path to the video file to upload"}, "caption": {"type": "string", "description": "Video caption/description"}, "hashtags": { "type": "array", "items": {"type": "string"}, "description": "List of hashtags (without #)", }, }, "required": ["video_path", "caption"], }, ),