Skip to main content
Glama

Spline MCP Server

by aydinfer
gaussian-splatting-tools.js8.46 kB
/** * Gaussian Splatting Tools for Spline.design * * Tools for working with 3D Gaussian Splatting in Spline. */ import { z } from "zod"; import { fetchFromSplineApi, updateSplineObject } from "../../utils/api-client.js"; /** * Register Gaussian Splatting tools * @param {McpServer} server - The MCP server instance */ export function registerGaussianSplattingTools(server) { server.tool( "importGaussianSplatting", { sceneId: z.string().min(1).describe("Scene ID"), url: z.string().url().describe("URL to Gaussian Splatting data (.splat, .ply)"), position: z.object({ x: z.number().default(0), y: z.number().default(0), z: z.number().default(0), }).optional().describe("Position in 3D space"), rotation: z.object({ x: z.number().default(0), y: z.number().default(0), z: z.number().default(0), }).optional().describe("Rotation in degrees"), scale: z.number().positive().default(1).describe("Uniform scale factor"), parameters: z.object({ quality: z.enum(["low", "medium", "high", "ultra"]).default("high").describe("Render quality"), pointSize: z.number().positive().optional().describe("Point size multiplier"), opacity: z.number().min(0).max(1).default(1).describe("Global opacity"), colorAdjustment: z.object({ brightness: z.number().min(-1).max(1).default(0).describe("Brightness adjustment"), contrast: z.number().min(-1).max(1).default(0).describe("Contrast adjustment"), saturation: z.number().min(-1).max(1).default(0).describe("Saturation adjustment"), hue: z.number().min(-180).max(180).default(0).describe("Hue rotation in degrees"), }).optional().describe("Color adjustment parameters"), clipPlanes: z.array(z.object({ normal: z.object({ x: z.number(), y: z.number(), z: z.number(), }).describe("Plane normal vector"), distance: z.number().describe("Plane distance from origin"), })).optional().describe("Clipping planes"), }).optional().describe("Gaussian Splatting parameters"), }, async ({ sceneId, url, position, rotation, scale, parameters }) => { try { const result = await fetchFromSplineApi(`/scenes/${sceneId}/objects/gaussian-splatting`, { method: "POST", body: JSON.stringify({ url, position, rotation, scale, parameters, }), }); return { content: [{ type: "text", text: `Imported Gaussian Splatting (ID: ${result.objectId})` }] }; } catch (error) { return { content: [{ type: "text", text: `Error importing Gaussian Splatting: ${error.message}` }], isError: true }; } } ); server.tool( "updateGaussianSplatting", { sceneId: z.string().min(1).describe("Scene ID"), objectId: z.string().min(1).describe("Gaussian Splatting object ID"), parameters: z.record(z.any()).describe("Updated Gaussian Splatting parameters"), }, async ({ sceneId, objectId, parameters }) => { try { await updateSplineObject(sceneId, objectId, { parameters, }); return { content: [{ type: "text", text: `Updated Gaussian Splatting ${objectId}` }] }; } catch (error) { return { content: [{ type: "text", text: `Error updating Gaussian Splatting: ${error.message}` }], isError: true }; } } ); server.tool( "createGaussianSplattingFromImages", { sceneId: z.string().min(1).describe("Scene ID"), imageUrls: z.array(z.string().url()).min(5).describe("URLs to input images (min 5 images)"), cameraParameters: z.array(z.object({ position: z.object({ x: z.number(), y: z.number(), z: z.number(), }).describe("Camera position"), rotation: z.object({ x: z.number(), y: z.number(), z: z.number(), }).describe("Camera rotation"), fov: z.number().positive().default(60).describe("Field of view in degrees"), })).optional().describe("Camera parameters for each image (if known)"), quality: z.enum(["draft", "medium", "high"]).default("medium").describe("Reconstruction quality"), position: z.object({ x: z.number().default(0), y: z.number().default(0), z: z.number().default(0), }).optional().describe("Position in 3D space for result"), autoOrient: z.boolean().default(true).describe("Automatically orient the result"), }, async ({ sceneId, imageUrls, cameraParameters, quality, position, autoOrient }) => { try { // This operation is typically long-running, so we return a job ID const result = await fetchFromSplineApi(`/scenes/${sceneId}/objects/gaussian-splatting/from-images`, { method: "POST", body: JSON.stringify({ imageUrls, cameraParameters, quality, position, autoOrient, }), }); return { content: [{ type: "text", text: `Started Gaussian Splatting creation from ${imageUrls.length} images (Job ID: ${result.jobId}). You can check progress with the "checkGaussianSplattingJob" tool.` }] }; } catch (error) { return { content: [{ type: "text", text: `Error creating Gaussian Splatting: ${error.message}` }], isError: true }; } } ); server.tool( "checkGaussianSplattingJob", { sceneId: z.string().min(1).describe("Scene ID"), jobId: z.string().min(1).describe("Gaussian Splatting job ID"), }, async ({ sceneId, jobId }) => { try { const result = await fetchFromSplineApi(`/scenes/${sceneId}/objects/gaussian-splatting/jobs/${jobId}`, { method: "GET", }); if (result.status === "completed") { return { content: [{ type: "text", text: `Gaussian Splatting job completed successfully! Object ID: ${result.objectId}` }] }; } else if (result.status === "failed") { return { content: [{ type: "text", text: `Gaussian Splatting job failed: ${result.error}` }], isError: true }; } else { return { content: [{ type: "text", text: `Gaussian Splatting job is ${result.status}. Progress: ${result.progress}%` }] }; } } catch (error) { return { content: [{ type: "text", text: `Error checking Gaussian Splatting job: ${error.message}` }], isError: true }; } } ); server.tool( "convertMeshToGaussianSplatting", { sceneId: z.string().min(1).describe("Scene ID"), objectId: z.string().min(1).describe("Source mesh object ID"), quality: z.enum(["draft", "medium", "high"]).default("medium").describe("Conversion quality"), samplingDensity: z.number().positive().default(1).describe("Point sampling density multiplier"), preserveOriginal: z.boolean().default(true).describe("Keep the original mesh"), }, async ({ sceneId, objectId, quality, samplingDensity, preserveOriginal }) => { try { const result = await fetchFromSplineApi(`/scenes/${sceneId}/objects/${objectId}/to-gaussian-splatting`, { method: "POST", body: JSON.stringify({ quality, samplingDensity, preserveOriginal, }), }); return { content: [{ type: "text", text: `Converted mesh to Gaussian Splatting (ID: ${result.objectId})` }] }; } catch (error) { return { content: [{ type: "text", text: `Error converting mesh to Gaussian Splatting: ${error.message}` }], isError: true }; } } ); }

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/aydinfer/spline-mcp-server'

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