npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

roblox-mcp-server

v3.1.3

Published

An MCP server for interacting with Roblox Game Clients (Delta, etc) over WebSocket+HTTP, with a server side decompile pipeline and in game UI.

Readme


pick your MCP client

| client | guide | |-------------------------------------------|--------------------------------------| | Claude Desktop + Claude Code | CLAUDE_MCP.md | | Cursor | CURSOR_MCP.md | | Windsurf | WINDSURF_MCP.md | | VS Code (Copilot Chat) | VSCODE_MCP.md | | Zed | ZED_MCP.md | | Cline | CLINE_MCP.md | | Roo Code | ROOCODE_MCP.md | | Continue | CONTINUE_MCP.md |

each file has the exact config path, JSON shape, and copy paste snippet for that client.


what it does

bridges any MCP capable client (Claude Code, Cursor, Windsurf, etc) to a Roblox executor running in a real game session. lets the model decompile scripts, spy remotes, click buttons, type text, fire signals, run lua, all from chat.

upstream by notpoiu. this fork rebuilds the decompile path end to end and adds a real UI.


new in v3.1.2

token-safe MCP responses

every tool call used to dump pretty-printed Lua with a { "value", n = 1 } envelope. on a 200k context that adds up fast. v3.1.2:

  • connector serializes compact, no Prettify, no n = 1 array tail for single-value returns
  • server-side tokensafe() post-filter strips legacy envelopes from older connectors and hard-caps each response at 12000 chars with a clean truncation footer
  • list-clients JSON dropped from pretty to compact (4-5x smaller payload)
  • default limits trimmed:
    • script-grep limit 50 → 20, maxMatchesPerScript 20 → 5, contextLines 2 → 1
    • dump-visible-ui maxItems 500 → 150
    • get-console-output, search-instances, get-remote-spy-logs limit 50 → 25
    • get-descendants-tree maxChildren 50 → 20

bump the per-tool limit explicitly when you actually need the breadth, otherwise the new defaults already cover 90% of asks for a fraction of the tokens.

device aware throttling (anti crash/lag)

connector now detects mobile / console / desktop on boot and tunes everything heavy.

| profile | upload batch | scan chunk | scan sleep | spy interval | |----------|--------------|------------|------------|--------------| | mobile | 3 | 80 | 60ms | 600ms | | console | 4 | 120 | 40ms | 400ms | | desktop | 8 | 250 | 10ms | 200ms |

decomp mapping, gc scans, spy polling all read from DeviceProfile. mobile and Xbox stop choking under the desktop tuned defaults.

push events instead of polling

connector ↔ server bridge now carries outbound event messages. server fans them out over an SSE stream at /api/events (filter with ?kind= and ?clientId=).

new MCP tool subscribe-remote flips a diff poller inside the connector. every new Cobalt remote call gets pushed as a remote-call event. agents stop hammering get-remote-spy-logs in a loop.

hot reload

new MCP tool hot-reload ships a Luau chunk to the active client. state survives across reloads via getgenv().STATE. takes either inline source or a server local filePath.

-- inside your live script
getgenv().STATE.counter = (getgenv().STATE.counter or 0) + 1
print("reloaded", getgenv().STATE.counter)

new in v3.0.0

decompile pipeline that doesn't fail

old chain (lua.expert then medal then konstant) ran client side, fell over on big scripts. PlayerModule decompile would 50x after 112 seconds.

new pipeline lives on the server:

client sends bytecode
    ↓
[1] SHA384 cache hit       instant return (every decompile cached forever)
    ↓
[2] CoreScript path?       pull pristine source from MaximumADHD/Roblox-Client-Tracker
    ↓
[3] race lua.expert + medal + konstant in parallel    first valid wins
    ↓
[4] fall back to native executor decompile

PlayerModule and all CoreScripts now return clean Roblox source in under a second.

new HTTP api

| route | what it does | |----------------------------------|-----------------------------------------------------------------| | POST /api/decompile | the orchestrator above. takes bytecode, returns source | | POST /api/decompile/disasm | full bytecode disasm with LOP_NATIVECALL highlighting | | POST /api/decompile/constants | extract every string / number / import without decompiling | | POST /api/decompile/diff | per proto hash diff between two bytecode versions | | GET /api/decompile/stats | cache hit rate, provider wins, entry count | | GET /api/version | server + connector version, platform aware update hints | | GET /script.luau | served connector (always in sync with running server) | | GET /ui.luau | in game settings + connection UI |

in game UI

new ui.luau ships a glassy connection panel. drop it in the executor:

loadstring(game:HttpGet("https://gitlab.com/DexCodeSX/roblox-executor-mcp/-/raw/main/ui.luau"))()

features:

  • bridge URL input with paste / clear / autosave
  • version pill that turns green / yellow / red based on /api/version compare
  • platform aware "how to update" hint (macos / linux / termux / wsl / windows)
  • live activity log of the handshake
  • settings drawer with three toggles (websocket / lazy decomp / autoconnect)
  • drag works on mouse + touch (PC + mobile)
  • animated background orbs that drift behind the window
  • saved URL auto checks on open

version sync

connector reports its version + platform to /api/version. server replies with one of:

| status | what happens | |------------|-------------------------------------------------------------------| | current | green pill, boots normally | | outdated | yellow banner with platform specific update command, boots anyway | | blocked | red banner, boot refused, you must update first |

MIN_BOOTABLE_CONNECTOR in src/http/routes/api/version.ts gates blocked vs outdated. bump it when the server adds a contract the old connector can't speak.


install

via npm (recommended):

npm install -g roblox-mcp-server
# postinstall prints the absolute boot path, something like:
#   /usr/lib/node_modules/roblox-mcp-server/dist/index.js
# point your MCP client at that path, or use the `roblox-mcp` bin directly

from source:

git clone https://gitlab.com/DexCodeSX/roblox-executor-mcp
cd roblox-executor-mcp
npm install
npm run build
npm start

server listens on :16384. dashboard at http://localhost:16384/.

mobile note

if you're running the server on the same Android phone (Termux) and connecting from Roblox on the same phone, localhost:16384 will NOT work. Roblox runs in its own network sandbox and can't see Termux. you MUST tunnel:

cloudflared tunnel --url http://localhost:16384

paste the https://*.trycloudflare.com URL into the in game UI. on Windows / macOS / Linux desktop, localhost works fine because the Roblox process and the server share the same OS network namespace.

the UI will refuse to connect to localhost from a mobile device and tell you to start a tunnel.

register with your MCP client

pick one from the clients table above. each file has the exact JSON / YAML for that client.

quick auto installer (Claude Code, Cursor, others where the CLI supports it):

npm run install:harnesses

writes the right config and prints the loader.


usage in roblox

simplest path, recommended:

loadstring(game:HttpGet("https://gitlab.com/DexCodeSX/roblox-executor-mcp/-/raw/main/ui.luau"))()

skip the UI, boot the connector directly:

getgenv().BridgeURL = "your-bridge-url"
loadstring(game:HttpGet("https://gitlab.com/DexCodeSX/roblox-executor-mcp/-/raw/main/connector.luau"))()

options:

getgenv().BridgeURL = "localhost:16384"
getgenv().DisableWebSocket = true                    -- http polling, steadier on mobile
getgenv().DisableInitialScriptDecompMapping = true   -- lazy: start mapping on first /grep call

architecture

src/
  decompile/
    cache.ts            SHA384 disk cache at ~/.roblox-mcp/decompile-cache/
    github-mirror.ts    maps CoreScript paths to MaximumADHD/Roblox-Client-Tracker
    providers.ts        lua.expert + medal + konstant racers
    orchestrator.ts     ties it all together
    luau-bytecode.ts    pure TS Luau bytecode reader (v3 through v6)
  http/
    routes/
      api/decompile.ts             POST orchestrator
      api/decompile/disasm.ts      POST bytecode disasm + LOP_NATIVECALL scan
      api/decompile/constants.ts   POST string/number/import extract
      api/decompile/diff.ts        POST per proto hash diff
      api/decompile/stats.ts       GET  cache stats
      api/version.ts               GET  version + platform compare
      script.luau.ts               GET  connector
      ui.luau.ts                   GET  in game UI
  tools/                  MCP tools (script-grep, get-script-content, etc)
  bridge/                 connector handshake, websocket fallback

cache survives restarts. entries are content addressed by bytecode SHA384, so the same decompile is never paid for twice across any client, any place, any session.


bytecode disassembler example

curl -X POST http://localhost:16384/api/decompile/disasm \
  -H 'Content-Type: application/json' \
  -d '{"bytecodeBase64":"BAUDfgEHQF..."}'

returns:

-- Bytecode v6, 142 strings, 17 protos
-- proto[0] init (params=0 ups=0 vararg=true stack=12 children=3)
    0: GETIMPORT          A=0 B=1 C=0    ; game.GetService
    1: NAMECALL           A=0 B=0 C=0 AUX=...  ; "GetService"

plus a nativeCalls array pointing at every LOP_NATIVECALL site. those skip the Lua VM and your hookmetamethod hooks won't see them mid execution. useful for AC analysis.


credits


not affiliated with Roblox Corporation. for research and learning. use responsibly.