CoolFace
Apppublic

RobinsAIWorld/ml-sharp

sourceHugging Faceupdated 9mo agoView on Hugging Face
1likes
mcp_server.py225 linesDownload Raw Back to root
1"""SHARP MCP Server for programmatic access to 3D Gaussian prediction.2 3Run standalone:4    uv run python mcp_server.py5 6Or integrate with MCP clients via stdio transport.7"""8 9from __future__ import annotations10 11import json12import os13from pathlib import Path14from typing import Literal15 16import torch17from mcp.server.fastmcp import FastMCP18 19from model_utils import (20    DEFAULT_OUTPUTS_DIR,21    ModelWrapper,22    TrajectoryType,23    get_global_model,24)25 26MCP_PORT: int = int(os.getenv("SHARP_MCP_PORT", "49201"))27 28mcp = FastMCP(29    "sharp",30    description="SHARP: Single-image 3D Gaussian scene prediction",31)32 33# -----------------------------------------------------------------------------34# Tools35# -----------------------------------------------------------------------------36 37 38@mcp.tool()39def sharp_predict(40    image_path: str,41    render_video: bool = True,42    trajectory_type: TrajectoryType = "rotate_forward",43    num_frames: int = 60,44    fps: int = 30,45    output_long_side: int | None = None,46) -> dict:47    """Predict 3D Gaussians from a single image.48 49    Args:50        image_path: Absolute path to input image (jpg/png/webp).51        render_video: Whether to render a camera trajectory video (requires CUDA).52        trajectory_type: Camera trajectory type (swipe/shake/rotate/rotate_forward).53        num_frames: Number of frames for video rendering.54        fps: Frames per second for video.55        output_long_side: Output resolution (longest side). None = match input.56 57    Returns:58        dict with keys:59            - ply_path: Path to exported PLY file60            - video_path: Path to rendered MP4 (or null if not rendered)61            - cuda_available: Whether CUDA was available62    """63    image_path_obj = Path(image_path)64    if not image_path_obj.exists():65        raise FileNotFoundError(f"Image not found: {image_path}")66 67    model = get_global_model()68    video_path, ply_path = model.predict_and_maybe_render(69        image_path_obj,70        trajectory_type=trajectory_type,71        num_frames=num_frames,72        fps=fps,73        output_long_side=output_long_side,74        render_video=render_video,75    )76 77    return {78        "ply_path": str(ply_path),79        "video_path": str(video_path) if video_path else None,80        "cuda_available": torch.cuda.is_available(),81    }82 83 84@mcp.tool()85def sharp_render(86    ply_path: str,87    trajectory_type: TrajectoryType = "rotate_forward",88    num_frames: int = 60,89    fps: int = 30,90    output_long_side: int | None = None,91) -> dict:92    """Render a video from an existing PLY file.93 94    Note: This requires re-predicting from the original image since Gaussians95    are not stored in standard PLY format. For now, returns an error.96    Future versions may support loading Gaussians from PLY.97 98    Args:99        ply_path: Path to PLY file (from previous prediction).100        trajectory_type: Camera trajectory type.101        num_frames: Number of frames.102        fps: Frames per second.103        output_long_side: Output resolution.104 105    Returns:106        dict with error message (feature not yet implemented).107    """108    return {109        "error": "Rendering from PLY not yet implemented. Use sharp_predict with render_video=True.",110        "hint": "PLY files store only point data, not the full Gaussian parameters needed for rendering.",111    }112 113 114@mcp.tool()115def list_outputs() -> dict:116    """List all generated output files (PLY and MP4).117 118    Returns:119        dict with keys:120            - outputs_dir: Path to outputs directory121            - ply_files: List of PLY file paths122            - video_files: List of MP4 file paths123    """124    outputs_dir = DEFAULT_OUTPUTS_DIR125    ply_files = sorted(outputs_dir.glob("*.ply"))126    video_files = sorted(outputs_dir.glob("*.mp4"))127 128    return {129        "outputs_dir": str(outputs_dir),130        "ply_files": [str(f) for f in ply_files],131        "video_files": [str(f) for f in video_files],132    }133 134 135# -----------------------------------------------------------------------------136# Resources137# -----------------------------------------------------------------------------138 139 140@mcp.resource("sharp://info")141def get_info() -> str:142    """Get SHARP server info including GPU status and configuration."""143    cuda_available = torch.cuda.is_available()144    gpu_info = []145 146    if cuda_available:147        for i in range(torch.cuda.device_count()):148            props = torch.cuda.get_device_properties(i)149            gpu_info.append({150                "index": i,151                "name": props.name,152                "total_memory_gb": round(props.total_memory / (1024**3), 2),153                "compute_capability": f"{props.major}.{props.minor}",154            })155 156    info = {157        "model": "SHARP (Apple ml-sharp)",158        "description": "Single-image 3D Gaussian scene prediction",159        "cuda_available": cuda_available,160        "cuda_device_count": torch.cuda.device_count() if cuda_available else 0,161        "gpus": gpu_info,162        "outputs_dir": str(DEFAULT_OUTPUTS_DIR),163        "checkpoint_sources": [164            "SHARP_CHECKPOINT_PATH env var",165            "HuggingFace Hub (apple/Sharp)",166            "Upstream CDN (torch.hub)",167        ],168        "env_vars": {169            "SHARP_CHECKPOINT_PATH": os.getenv("SHARP_CHECKPOINT_PATH", "(not set)"),170            "SHARP_KEEP_MODEL_ON_DEVICE": os.getenv("SHARP_KEEP_MODEL_ON_DEVICE", "1"),171            "CUDA_VISIBLE_DEVICES": os.getenv("CUDA_VISIBLE_DEVICES", "(not set)"),172        },173    }174 175    return json.dumps(info, indent=2)176 177 178@mcp.resource("sharp://help")179def get_help() -> str:180    """Get usage help for the SHARP MCP server."""181    help_text = """182# SHARP MCP Server183 184## Tools185 186### sharp_predict187Predict 3D Gaussians from a single image.188 189Parameters:190- image_path (required): Absolute path to input image191- render_video: Whether to render MP4 (default: true, requires CUDA)192- trajectory_type: swipe | shake | rotate | rotate_forward (default: rotate_forward)193- num_frames: Number of video frames (default: 60)194- fps: Video frame rate (default: 30)195- output_long_side: Output resolution, null = match input196 197### list_outputs198List all generated PLY and MP4 files.199 200## Resources201 202### sharp://info203Server info, GPU status, configuration.204 205### sharp://help206This help text.207 208## Environment Variables209 210- SHARP_MCP_PORT: MCP server port (default: 49201)211- SHARP_CHECKPOINT_PATH: Local checkpoint path override212- SHARP_KEEP_MODEL_ON_DEVICE: Keep model on GPU (default: 1)213- CUDA_VISIBLE_DEVICES: GPU selection (e.g., "0" or "0,1")214"""215    return help_text.strip()216 217 218# -----------------------------------------------------------------------------219# Main220# -----------------------------------------------------------------------------221 222if __name__ == "__main__":223    # Run as stdio transport for MCP clients224    mcp.run()225