Skip to content

About

Drive Roblox's Luau VM from Python or MCP via the macsploit dylib

Resources

Stars

97 stars

Watchers

1 watching

Forks

Latest commit

 

History

2 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

MCP-Sploit

drive roblox's luau vm from python or claude · over macsploit's own wire

tcpdump → IDA → 80 lines of python → game.Players[*]:Kick()


       ┌──────── MacSploit.app  (the official GUI)
       │
   ◄───┼──────── MCP-Sploit     (this project)
       │
       └──────── anything else that speaks the protocol
                         │
                         ▼
                   ┌───────────┐
                   │  Roblox   │
                   │ macsploit │ ◄─── injected dylib, owns the Lua state
                   │   dylib   │
                   └───────────┘

the idea

macsploit is a dylib that gets injected into Roblox. once it's in, it owns the lua state — it can compile and run any luau as if the game itself wrote it. the dylib also opens two local sockets:

tcp   127.0.0.1:5553-5563   single-client script-in
ws    127.0.0.1:8765        alternate channel

the MacSploit.app GUI you normally use is just a client of those sockets. nothing magical. so we cut the GUI out of the loop and connect to the dylib directly. from the dylib's perspective, MCP-Sploit and the official app are indistinguishable.

how the protocol got reversed

no fancy tools. one terminal:

$ sudo tcpdump -i lo0 -A 'tcp port 5553'

then click Execute in the official app. the wire format falls out:

offset  bytes                            meaning
 0      00 00 00 00 00 00 00 00          (zero / unused)
 8      LL LL LL LL                      body length, little-endian u32
12      00 00 00 00                      (zero / padding)
16      <body bytes>                     luau source, utf-8
N-2     0a 00                            "\n\0" terminator

→ mcp_sploit/protocols/tcp.py

the websocket on :8765 is even less exotic — a normal ws frame with {"op":"load","string":"<luau>"} inside. for the dylib internals i poked at the binary in IDA, but tcpdump did 95% of the work.

why you have to close MacSploit.app

the dylib's tcp listener is single-client. when MacSploit.app is open it's holding the slot — every connect() after that gets refused. quit the app and the slot is yours. roblox itself can keep running; the dylib stays injected the whole time.

(the websocket on :8765 doesn't have this restriction, so MCP-Sploit can fall back to it.)

getting output back

both channels are fire-and-forget — the dylib doesn't echo print over either socket. but it doesn't have to. roblox itself logs every print / warn / error to:

~/Library/Logs/Roblox/*Player*.log

…under the [FLog::Output] tag. so execute_and_capture is just:

1. wrap the script with begin/end marker prints
2. note current log size
3. send the script
4. tail the log until the end marker shows up

cleaner than sniffing the ws.


install

git clone https://github.com/Claude-Reverser/MCP-Sploit
cd MCP-Sploit
pip install -e .

requires macOS · python ≥ 3.10 · a working macsploit install.

use it

cli

mcp-sploit discover
mcp-sploit exec 'print("hi")'
mcp-sploit exec luau/demos/player_v2.luau
mcp-sploit exec-all luau/demos/esp.luau

python

from mcp_sploit import discover, execute, execute_all
from mcp_sploit.bundle import with_ui

discover()                  # [Instance(port=5553, protocol='tcp'), ...]
execute('print("hi")')
execute_all('print("hi")')  # → {5553: True, 5554: True}

# bundle the in-game ui lib so _G.mcpsploit_ui is available
execute(with_ui([[
    local ui  = _G.mcpsploit_ui
    local win = ui.window("demo")
    win:section("hi"):button("click", function() print("clicked") end)
]]))

mcp (claude code)

claude mcp add mcp-sploit --scope user -- mcp-sploit-mcp

then ask claude:

"discover any running roblox instances, then notify me with 'hello' and tail the last 20 lines of script output"

tool what it does
discover list active macsploit instances
execute run a luau script (fire-and-forget)
execute_on_all broadcast a script to every instance
notify top-right in-game notification
execute_and_capture run a script and tail its print/warn/error
tail_logs recent script output from the roblox client log

demos

luau/demos/
├── player_v2.luau   walkspeed · jump · gravity · fly · noclip
├── esp.luau         box / name / health / distance esp with a slider gui
├── aimbot.luau      camera lock with fov circle, smoothing, team check
├── combat.luau      esp + aimbot in one window (silent-aim hook included)
└── auto_roll.luau   toy auto-roller for a ugc roll game

each demo expects _G.mcpsploit_ui to be loaded — pass it through with_ui() from python or paste the lib first if you're running by hand.

layout

mcp_sploit/                 python
├── discovery.py              port scanner + Instance dataclass
├── executor.py               protocol dispatch
├── bundle.py                 prepend mcpsploit_ui to a script
├── logs.py                   roblox log tail / parse
├── mcp_server.py             fastmcp server
└── protocols/
    ├── tcp.py                wire format above
    └── websocket.py          rfc6455 by hand, no extra deps

luau/
├── lib/mcpsploit_ui.luau     in-game ui library
└── demos/                    examples (see above)

cli.py                        mcp-sploit {discover,exec,exec-all}

license / disclaimer

MIT.

for your own roblox sessions, private servers, and study. running an executor in public games is against roblox's tos — that's on you.

built by reading tcpdump -A output until the format clicked.

About

Drive Roblox's Luau VM from Python or MCP via the macsploit dylib

Resources

Stars

97 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages