Skip to main content
Glama

3D Asset Processing MCP

by GeoLibra
gltf-transform-api.ts5.68 kB
import { Router } from 'express'; import logger from '../utils/logger'; import * as fs from 'fs'; import * as path from 'path'; import { GltfTransformExecutor, GltfTransformExecOptions } from '../core/gltf-transform-executor'; import { desiredExtFrom } from '../utils/gltf-constants'; const router = Router(); /** * Process a glTF file with custom options * POST /api/transform/process */ router.post('/process', async (req, res) => { try { const options: GltfTransformExecOptions = req.body; if (!options?.inputPath) { return res.status(400).json({ error: 'Input path is required' }); } if (!fs.existsSync(options.inputPath)) { return res.status(404).json({ error: 'Input file not found' }); } // Ensure outputPath if (!options.outputPath) { const inputExt = path.extname(options.inputPath); const baseName = path.basename(options.inputPath, inputExt); const dirName = path.dirname(options.inputPath); const desiredExt = desiredExtFrom({ outputFormat: options.outputFormat, binary: options.binary }); options.outputPath = path.join(dirName, `${baseName}_transformed${desiredExt}`); } const executor = new GltfTransformExecutor(); const command = await executor.execute(options); res.json({ success: true, data: { inputPath: options.inputPath, outputPath: options.outputPath, command } }); } catch (error) { logger.error('API error:', error); res.status(500).json({ error: error instanceof Error ? error.message : String(error) }); } }); /** * Optimize a glTF file * POST /api/transform/optimize */ router.post('/optimize', async (req, res) => { try { const { inputPath } = req.body as { inputPath?: string; outputPath?: string }; if (!inputPath) return res.status(400).json({ error: 'Input path is required' }); if (!fs.existsSync(inputPath)) return res.status(404).json({ error: 'Input file not found' }); const execOptions: GltfTransformExecOptions = { inputPath, outputPath: req.body.outputPath, outputFormat: req.body.outputFormat, binary: req.body.binary, // optimize via gltf-transform: just include 'optimize' in command via executor default pipeline }; const executor = new GltfTransformExecutor(); const command = await executor.execute(execOptions); res.json({ success: true, data: { inputPath, outputPath: execOptions.outputPath, command } }); } catch (error) { logger.error('API error:', error); res.status(500).json({ error: error instanceof Error ? error.message : String(error) }); } }); /** * Simplify a glTF file's geometry * POST /api/transform/simplify */ router.post('/simplify', async (req, res) => { try { const { inputPath } = req.body as { inputPath?: string; ratio?: number; outputPath?: string }; if (!inputPath) return res.status(400).json({ error: 'Input path is required' }); if (!fs.existsSync(inputPath)) return res.status(404).json({ error: 'Input file not found' }); const execOptions: GltfTransformExecOptions = { inputPath, outputPath: req.body.outputPath, simplify: true, simplifyOptions: { ratio: req.body.ratio ?? 0.5 } }; const executor = new GltfTransformExecutor(); const command = await executor.execute(execOptions); res.json({ success: true, data: { inputPath, outputPath: execOptions.outputPath, command } }); } catch (error) { logger.error('API error:', error); res.status(500).json({ error: error instanceof Error ? error.message : String(error) }); } }); /** * Compress textures in a glTF file * POST /api/transform/compress-textures */ router.post('/compress-textures', async (req, res) => { try { const { inputPath } = req.body as { inputPath?: string; outputPath?: string; textureOptions?: any }; if (!inputPath) return res.status(400).json({ error: 'Input path is required' }); if (!fs.existsSync(inputPath)) return res.status(404).json({ error: 'Input file not found' }); const execOptions: GltfTransformExecOptions = { inputPath, outputPath: req.body.outputPath, textureCompress: true, textureFormat: req.body?.textureOptions?.format, // quality 等细节由 executor/CLI 侧处理或忽略 }; const executor = new GltfTransformExecutor(); const command = await executor.execute(execOptions); res.json({ success: true, data: { inputPath, outputPath: execOptions.outputPath, command} }); } catch (error) { logger.error('API error:', error); res.status(500).json({ error: error instanceof Error ? error.message : String(error) }); } }); /** * Apply Draco compression to a glTF file * POST /api/transform/draco */ router.post('/draco', async (req, res) => { try { const { inputPath } = req.body as { inputPath?: string; outputPath?: string; dracoOptions?: any }; if (!inputPath) return res.status(400).json({ error: 'Input path is required' }); if (!fs.existsSync(inputPath)) return res.status(404).json({ error: 'Input file not found' }); const execOptions: GltfTransformExecOptions = { inputPath, outputPath: req.body.outputPath, draco: true, dracoOptions: req.body.dracoOptions }; const executor = new GltfTransformExecutor(); const command = await executor.execute(execOptions); res.json({ success: true, data: { inputPath, outputPath: execOptions.outputPath, command } }); } catch (error) { logger.error('API error:', error); res.status(500).json({ error: error instanceof Error ? error.message : String(error) }); } }); export default router;

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/GeoLibra/3d-asset-processing-mcp'

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