Files
ClaudeCode-Roblox-Studio-MCP/roblox-plugin/RobloxMCPServer_HTTP.lua
Admin a66533206f Add FPS game example, auto-connect plugin, and Python injection tools
- Updated RobloxMCPPlugin with HTTP polling (auto-enables HttpService)
- Added 20-weapon FPS game example (CoD-style)
- Added Python studio-inject.py for command bar injection via Win32 API
- Added auto-connect setup scripts (VBS + PowerShell)
- Updated MCP server with all FPS game tools

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-31 16:57:35 +04:00

240 lines
6.3 KiB
Lua

-- Roblox MCP Server - HTTP Polling Version
-- This version polls the MCP server for commands via HTTP
local HttpService = game:GetService("HttpService")
local RunService = game:GetService("RunService")
-- Configuration
local MCP_SERVER_URL = "http://127.0.0.1:37423"
local POLL_INTERVAL = 0.5 -- seconds
local DEBUG = true
-- State
local isRunning = true
local lastCommandId = 0
-- Logging
local function log(msg)
if DEBUG then
print("[RobloxMCP] " .. msg)
end
end
-- Get object by path
local function getObjectFromPath(path)
if not path or path == "" then return nil end
if path == "game" or path == "Game" then return game end
if path == "Workspace" or path == "workspace" then return workspace end
local parts = {}
for part in string.gmatch(path, "[^%.]+") do
table.insert(parts, part)
end
local obj = game
for _, part in ipairs(parts) do
if part == "Workspace" or part == "workspace" then
obj = workspace
elseif typeof(obj) == "Instance" and obj:FindFirstChild(part) then
obj = obj[part]
else
return nil
end
end
return obj
end
-- Create object at path
local function createObjectAt(path, className, properties)
local lastDot = string.find(path, "%.[^%.]+$")
local parentPath = lastDot and string.sub(path, 1, lastDot - 1) or "game"
local objectName = lastDot and string.sub(path, lastDot + 1) or path
local parent = getObjectFromPath(parentPath)
if not parent then return nil, "Parent not found" end
local obj = Instance.new(className)
obj.Name = objectName
if properties then
for prop, value in pairs(properties) do
pcall(function() obj[prop] = value end)
end
end
obj.Parent = parent
return obj
end
-- Command handlers
local handlers = {}
handlers.createPart = function(params)
local props = {
Name = params.partName,
Anchored = params.anchored ~= false,
Shape = Enum.PartType.Block,
}
if params.position then
props.Position = Vector3.new(params.position.x or 0, params.position.y or 0, params.position.z or 0)
end
if params.size then
props.Size = Vector3.new(params.size.x or 4, params.size.y or 1, params.size.z or 2)
end
if params.color then
pcall(function() props.BrickColor = BrickColor.new(params.color) end)
end
local part = createObjectAt((params.parentPath or "Workspace") .. "." .. params.partName, "Part", props)
return {success = part ~= nil}
end
handlers.createScript = function(params)
local obj = createObjectAt(params.path .. "." .. params.scriptName, params.scriptType or "Script", {Name = params.scriptName})
if obj then
obj.Source = params.source
return {success = true}
end
return {success = false}
end
handlers.setProperty = function(params)
local obj = getObjectFromPath(params.path)
if not obj then return {success = false, error = "Not found"} end
local value = params.value
if params.property == "Position" or params.property == "Size" then
value = Vector3.new(value.x, value.y, value.z)
elseif params.property == "Color3" then
value = Color3.new(value.r, value.g, value.b)
end
pcall(function() obj[params.property] = value end)
return {success = true}
end
handlers.executeCode = function(params)
local fn, err = loadstring(params.code)
if not fn then return {success = false, error = err} end
local ok = pcall(fn)
return {success = ok}
end
handlers.getHierarchy = function(params)
local obj = getObjectFromPath(params.path or "Workspace")
if not obj then return {success = false, error = "Not found"} end
local function build(obj, depth)
if depth <= 0 then return nil end
local children = {}
for _, child in ipairs(obj:GetChildren()) do
table.insert(children, {
name = child.Name,
className = child.ClassName,
})
end
return children
end
return {success = true, children = build(obj, params.depth or 2)}
end
handlers.importGLB = function(params)
-- Import GLB model into Roblox Studio
-- GLB files need to be imported via the Editor API for assets
-- For now, we'll create a placeholder model with instructions
local parent = getObjectFromPath(params.parentPath or "Workspace")
if not parent then
return {success = false, error = "Parent path not found"}
end
-- Create a model to hold the imported GLB
local model = Instance.new("Model")
model.Name = params.modelName or "ImportedGLB"
model.Parent = parent
-- Create a placeholder part with info
local placeholder = Instance.new("Part")
placeholder.Name = "GLB_Placeholder"
placeholder.Size = Vector3.new(4, 4, 4)
placeholder.Position = Vector3.new(0, 5, 0)
placeholder.Anchored = true
placeholder.BrickColor = BrickColor.new("Bright blue")
placeholder.Transparency = 0.5
placeholder.Parent = model
-- Add a note
local info = Instance.new("StringValue")
info.Name = "ImportInfo"
info.Value = "GLB Import: Use the 3D Importer (File > Import 3D) or Editor Service to import GLB files. This is a placeholder."
info.Parent = model
return {
success = true,
modelPath = (params.parentPath or "Workspace") .. "." .. params.modelName,
note = "GLB files require manual import via Roblox Studio's 3D Importer or Editor Service API"
}
end
-- Poll for commands
local function pollForCommands()
local success, response = pcall(function()
return HttpService:RequestAsync({
Url = MCP_SERVER_URL .. "/poll?last=" .. lastCommandId,
Method = "GET",
})
end)
if success and response.Success then
local data = HttpService:JSONDecode(response.Body)
if data.commands then
for _, cmd in ipairs(data.commands) do
log("Got command: " .. cmd.command)
lastCommandId = cmd.id
local handler = handlers[cmd.command]
local result = {success = false, error = "Unknown command"}
if handler then
local ok, ret = pcall(handler, cmd.params)
if ok then
result = ret
else
result = {success = false, error = tostring(ret)}
end
end
-- Send result back
pcall(function()
HttpService:RequestAsync({
Url = MCP_SERVER_URL .. "/result",
Method = "POST",
Headers = {["Content-Type"] = "application/json"},
Body = HttpService:JSONEncode({
id = cmd.id,
result = result
})
})
end)
end
end
end
end
-- Main loop
log("Starting Roblox MCP Server (HTTP Polling)")
log("MCP Server: " .. MCP_SERVER_URL)
RunService.Heartbeat:Connect(function()
if isRunning then
pcall(pollForCommands)
end
end)
log("Roblox MCP Server is running!")