upload_project
Upload files or directories to Yourware for deployment and project showcasing. Supports single files like HTML or entire project directories using absolute paths.
Instructions
Upload a file or directory to yourware, might be a dist/out directory or a single html file. Use absolute path if possible. For multiple files, you should move them to a directory first, then use this tool to upload the directory
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| file_path | Yes | ||
| cwd | No |
Implementation Reference
- yourware_mcp/app.py:65-182 (handler)The handler function for 'upload_project' tool. It handles zipping the file or directory, uploading to the Yourware API using credentials, and deploying the project. Returns success status and project URLs.async def upload_project( # noqa: C901 file_path: Annotated[ str, "The path to the dist/out directory or single file. If ends with /, it will be treated as a directory", ], cwd: Annotated[ str | None, "The current working directory to resolve relative paths from, should be a absolute path", ] = None, ): if cwd: cwd_path = Path(cwd).expanduser().resolve() file_path = cwd_path / file_path else: file_path = Path(file_path) file_path = file_path.expanduser().resolve() try: credentials = Credentials.load() except FileNotFoundError: return { "success": False, "message": "Credentials not found", "help": "Run `create_api_key` to create one", } if not await credentials.check_credentials(): return { "success": False, "message": "Credentials are invalid", "help": "Call `create_api_key` to create one", } client = get_client(credentials) # 1. Create a zip in memory zip_buffer = io.BytesIO() with zipfile.ZipFile(zip_buffer, "w", zipfile.ZIP_DEFLATED) as zip_file: if file_path.is_dir(): # 2. Zip the directory into it for root, dirs, files in os.walk(file_path): # Skip .git directories if ".git" in dirs: dirs.remove(".git") # This modifies dirs in-place to prevent os.walk from traversing .git for file in files: file_full_path = Path(root) / file arc_name = file_full_path.relative_to(file_path) zip_file.write(file_full_path, arcname=arc_name) else: # Zip the single file zip_file.write(file_path, arcname=file_path.name) # Get the zip content zip_buffer.seek(0) zip_content = zip_buffer.getvalue() zip_size = len(zip_content) # 3. Call /api/v1/files/upload for upload infos upload_response = await client.post( "/api/v1/files/upload", json={ "files": [ { "file_name": "source_code.zip", "file_size": zip_size, "mime_type": "application/zip", } ], "event_type": "source_code", "is_public": False, }, ) if upload_response.status_code != 200: return { "success": False, "message": f"Failed to get upload info: {upload_response.text}", } upload_data = upload_response.json() upload_info = upload_data["data"]["upload_infos"][0] file_id = upload_info["file_id"] upload_url = upload_info["upload_url"] fields = upload_info["fields"] # 4. Upload the zip to the upload url files = {"file": ("source_code.zip", zip_content, "application/zip")} form_data = {**fields} async with httpx.AsyncClient() as upload_client: upload_result = await upload_client.post(upload_url, data=form_data, files=files) if upload_result.status_code not in (200, 201, 204): return { "success": False, "message": f"Failed to upload file: {upload_result.text}", } # 5. Call /api/v1/projects/deploy with the file_id deploy_response = await client.post("/api/v1/projects/deploy", json={"file_id": file_id}) if deploy_response.status_code != 200: return { "success": False, "message": f"Failed to deploy project: {deploy_response.text}", } deploy_data = deploy_response.json() project_data = deploy_data["data"] return { "success": True, "message": "Project uploaded successfully", "project_url": project_data["project_url"], "iframe_url": project_data["iframe_url"], }
- yourware_mcp/app.py:61-64 (registration)The @mcp.tool decorator registers the upload_project function with the MCP server, including the tool description.@mcp.tool( description="Upload a file or directory to yourware, might be a dist/out directory or a single html file. Use absolute path if possible. " "For multiple files, you should move them to a directory first, then use this tool to upload the directory" )
- yourware_mcp/app.py:66-74 (schema)Input schema defined via Annotated types for file_path and cwd parameters, used by FastMCP for tool schema generation.file_path: Annotated[ str, "The path to the dist/out directory or single file. If ends with /, it will be treated as a directory", ], cwd: Annotated[ str | None, "The current working directory to resolve relative paths from, should be a absolute path", ] = None, ):