Skip to main content
Glama

Roblox Studio MCP Server

index.ts11.9 kB
import { StudioHttpClient } from './studio-client.js'; import { BridgeService } from '../bridge-service.js'; export class RobloxStudioTools { private client: StudioHttpClient; constructor(bridge: BridgeService) { this.client = new StudioHttpClient(bridge); } // File System Tools async getFileTree(path: string = '') { const response = await this.client.request('/api/file-tree', { path }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async searchFiles(query: string, searchType: string = 'name') { const response = await this.client.request('/api/search-files', { query, searchType }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Studio Context Tools async getPlaceInfo() { const response = await this.client.request('/api/place-info', {}); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async getServices(serviceName?: string) { const response = await this.client.request('/api/services', { serviceName }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async searchObjects(query: string, searchType: string = 'name', propertyName?: string) { const response = await this.client.request('/api/search-objects', { query, searchType, propertyName }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Property & Instance Tools async getInstanceProperties(instancePath: string) { if (!instancePath) { throw new Error('Instance path is required for get_instance_properties'); } const response = await this.client.request('/api/instance-properties', { instancePath }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async getInstanceChildren(instancePath: string) { if (!instancePath) { throw new Error('Instance path is required for get_instance_children'); } const response = await this.client.request('/api/instance-children', { instancePath }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async searchByProperty(propertyName: string, propertyValue: string) { if (!propertyName || !propertyValue) { throw new Error('Property name and value are required for search_by_property'); } const response = await this.client.request('/api/search-by-property', { propertyName, propertyValue }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async getClassInfo(className: string) { if (!className) { throw new Error('Class name is required for get_class_info'); } const response = await this.client.request('/api/class-info', { className }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Project Tools async getProjectStructure(path?: string, maxDepth?: number, scriptsOnly?: boolean) { const response = await this.client.request('/api/project-structure', { path, maxDepth, scriptsOnly }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Property Modification Tools async setProperty(instancePath: string, propertyName: string, propertyValue: any) { if (!instancePath || !propertyName) { throw new Error('Instance path and property name are required for set_property'); } const response = await this.client.request('/api/set-property', { instancePath, propertyName, propertyValue }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async massSetProperty(paths: string[], propertyName: string, propertyValue: any) { if (!paths || paths.length === 0 || !propertyName) { throw new Error('Paths array and property name are required for mass_set_property'); } const response = await this.client.request('/api/mass-set-property', { paths, propertyName, propertyValue }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async massGetProperty(paths: string[], propertyName: string) { if (!paths || paths.length === 0 || !propertyName) { throw new Error('Paths array and property name are required for mass_get_property'); } const response = await this.client.request('/api/mass-get-property', { paths, propertyName }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Object Creation Tools async createObject(className: string, parent: string, name?: string) { if (!className || !parent) { throw new Error('Class name and parent are required for create_object'); } const response = await this.client.request('/api/create-object', { className, parent, name }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async createObjectWithProperties(className: string, parent: string, name?: string, properties?: Record<string, any>) { if (!className || !parent) { throw new Error('Class name and parent are required for create_object_with_properties'); } const response = await this.client.request('/api/create-object', { className, parent, name, properties }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async massCreateObjects(objects: Array<{className: string, parent: string, name?: string}>) { if (!objects || objects.length === 0) { throw new Error('Objects array is required for mass_create_objects'); } const response = await this.client.request('/api/mass-create-objects', { objects }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async massCreateObjectsWithProperties(objects: Array<{className: string, parent: string, name?: string, properties?: Record<string, any>}>) { if (!objects || objects.length === 0) { throw new Error('Objects array is required for mass_create_objects_with_properties'); } const response = await this.client.request('/api/mass-create-objects-with-properties', { objects }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async deleteObject(instancePath: string) { if (!instancePath) { throw new Error('Instance path is required for delete_object'); } const response = await this.client.request('/api/delete-object', { instancePath }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Smart Duplication Tools async smartDuplicate( instancePath: string, count: number, options?: { namePattern?: string; // e.g., "Button{n}" where {n} is replaced with index positionOffset?: [number, number, number]; // X, Y, Z offset per duplicate rotationOffset?: [number, number, number]; // X, Y, Z rotation offset per duplicate scaleOffset?: [number, number, number]; // X, Y, Z scale multiplier per duplicate propertyVariations?: Record<string, any[]>; // Property name to array of values targetParents?: string[]; // Different parent for each duplicate } ) { if (!instancePath || count < 1) { throw new Error('Instance path and count > 0 are required for smart_duplicate'); } const response = await this.client.request('/api/smart-duplicate', { instancePath, count, options }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async massDuplicate( duplications: Array<{ instancePath: string; count: number; options?: { namePattern?: string; positionOffset?: [number, number, number]; rotationOffset?: [number, number, number]; scaleOffset?: [number, number, number]; propertyVariations?: Record<string, any[]>; targetParents?: string[]; } }> ) { if (!duplications || duplications.length === 0) { throw new Error('Duplications array is required for mass_duplicate'); } const response = await this.client.request('/api/mass-duplicate', { duplications }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Calculated Property Tools async setCalculatedProperty( paths: string[], propertyName: string, formula: string, variables?: Record<string, any> ) { if (!paths || paths.length === 0 || !propertyName || !formula) { throw new Error('Paths, property name, and formula are required for set_calculated_property'); } const response = await this.client.request('/api/set-calculated-property', { paths, propertyName, formula, variables }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Relative Property Tools async setRelativeProperty( paths: string[], propertyName: string, operation: 'add' | 'multiply' | 'divide' | 'subtract' | 'power', value: any, component?: 'X' | 'Y' | 'Z' // For Vector3/UDim2 properties ) { if (!paths || paths.length === 0 || !propertyName || !operation || value === undefined) { throw new Error('Paths, property name, operation, and value are required for set_relative_property'); } const response = await this.client.request('/api/set-relative-property', { paths, propertyName, operation, value, component }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } // Script Management Tools async getScriptSource(instancePath: string) { if (!instancePath) { throw new Error('Instance path is required for get_script_source'); } const response = await this.client.request('/api/get-script-source', { instancePath }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } async setScriptSource(instancePath: string, source: string) { if (!instancePath || typeof source !== 'string') { throw new Error('Instance path and source code string are required for set_script_source'); } const response = await this.client.request('/api/set-script-source', { instancePath, source }); return { content: [ { type: 'text', text: JSON.stringify(response, null, 2) } ] }; } }

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/boshyxd/robloxstudio-mcp'

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