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

utmt-mcp

v0.3.2

Published

MCP server for reading GameMaker data files via UndertaleModCli

Readme

utmt-mcp

中文 · English

通过 UndertaleModCli 读取和导出 GameMaker 数据文件(.win.ios.droid.unx)的 MCP 服务器。

专为 LLM 工具调用而设计 —— 所有输出均为干净的 JSON,实体按名称查找。

跨平台 —— 支持 Windows、macOS、Linux。UndertaleModCli 为这三个平台都提供了官方构建。

快速开始

npx utmt-mcp

或全局安装:

npm install -g utmt-mcp
utmt-mcp

环境要求

  • Node.js 18+
  • .NET 运行时(UndertaleModCli 需要)
  • UndertaleModCli —— 加入 PATH,或通过环境变量 / 工具参数指定

安装 UndertaleModCli

GitHub Releases 下载对应平台的构建包,解压后任选一种方式:

  • 把可执行文件加入系统 PATH,或
  • UTMT_CLI_PATH 环境变量设置为可执行文件的完整路径

在 Windows 上 CLI 二进制文件带 Windows 可执行文件后缀;macOS 和 Linux 上没有后缀。其余用法完全一致。

配置

环境变量

| 变量 | 说明 | |----------|-------------| | UTMT_CLI_PATH | UndertaleModCli 可执行文件的完整路径 |

MCP 客户端配置

在 MCP 客户端中(如 Claude Desktop、Cursor、Claude Code 等):

{
  "mcpServers": {
    "utmt": {
      "command": "npx",
      "args": ["-y", "utmt-mcp"],
      "env": {
        "UTMT_CLI_PATH": "/path/to/UndertaleModCli"
      }
    }
  }
}

或者在每次工具调用时显式传入 CLI 路径(无需环境变量):

{
  "mcpServers": {
    "utmt": {
      "command": "npx",
      "args": ["-y", "utmt-mcp"]
    }
  }
}

工具

所有示例均为对真实数据文件的实际调用结果(长输出按需截断)。

utmt-info

获取 GameMaker 数据文件的概览信息。返回 JSON,包含项目名称、GM 版本、isYYC 标志和各类资源数量。

参数:

  • dataFilePath(必填)— 数据文件路径
  • cliPath(可选)— UndertaleModCli 路径

输入:

{"dataFilePath": "data.win"}

返回:

{"name":"VIVIDSTASIS","displayName":"vivid/stasis","gmVersion":"2024.14.1.0","isGMS2":true,"isYYC":false,"bytecodeVersion":17,"windowWidth":320,"windowHeight":180,"fps":60,"counts":{"sprites":2141,"sounds":664,"scripts":19375,"code":22033,"rooms":232,"gameObjects":814,"fonts":30,"backgrounds":5,"paths":0,"shaders":44,"strings":51932,"variables":16316,"functions":17835,"timelines":1,"embeddedTextures":100,"embeddedAudio":627,"texturePageItems":6782,"extensions":7,"sequences":0,"particleSystems":0}}

utmt-list-entities

列出指定类型的实体。返回 JSON 数组,包含索引、名称和简要属性。

参数:

  • dataFilePath(必填)
  • entityType(必填)— 可选值:spritessoundsscriptscoderoomsgameobjectsfontsbackgroundspathsshadersstringstimelinesembeddedtexturesembeddedaudioextensionssequencesparticlesystems
  • filter(可选)— 不区分大小写的名称过滤
  • offset(可选)— 分页偏移(默认:0)
  • limit(可选)— 最大返回数,1-500(默认:50)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "entityType": "sprites", "limit": 3}

返回:

[{"index":4,"name":"_filter_underwater_noise_sprite","width":256,"height":256,"frames":1,"origin":[0,0]},{"index":7,"name":"_filter_heathaze_noise_sprite","width":64,"height":64,"frames":1,"origin":[0,0]},{"index":987,"name":"sp_default_actor_sprite","width":16,"height":16,"frames":1,"origin":[0,0]}]

utmt-get-entity

获取单个实体的详细信息。返回 JSON,包含所有属性。

参数:

  • dataFilePath(必填)
  • entityType(必填)— 可选值:spritesoundscriptcoderoomgameobjectfontstringgeneralinfo
  • name(必填)— 实体名称(string 类型用数字索引;generalinfo 忽略此参数)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "entityType": "sprite", "name": "_filter_large_blur_noise"}

返回:

{"name":"_filter_large_blur_noise","width":32,"height":32,"originX":0,"originY":0,"frames":1,"transparent":false,"smooth":false,"preload":false,"bboxMode":0,"sepMasks":0,"marginLeft":0,"marginRight":31,"marginTop":0,"marginBottom":31,"collisionMasks":0,"spriteType":0,"playbackSpeed":30}

utmt-decompile-code

将代码条目反编译回 GML 源码。YYC 编译的游戏不可用。

参数:

  • dataFilePath(必填)
  • codeName(必填)— 代码条目名称(如 gml_Script_myFunction
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "codeName": "gml_Script_io_gamemaker_gm_effect_glow_1_0_0__effect_glow_script"}

返回(GML 源码,节选):

function gml_Script_io_gamemaker_gm_effect_glow_1_0_0__effect_glow() constructor
{
    static shader = _effect_glow_shader;
    static u_GlowRadius = shader_get_uniform(shader, "g_GlowRadius");
    ...
}

utmt-export-entity

将单个实体导出到磁盘。

参数:

  • dataFilePath(必填)
  • entityType(必填)— 可选值:spritesoundcodeembeddedtexture
  • name(必填)— 实体名称(embeddedtexture 用数字索引)
  • outputPath(必填)— 输出文件或目录路径
  • cliPath(可选)

导出格式:

  • sprite → 输出目录中的 PNG 帧
  • sound → .ogg 或 .wav 文件
  • code → 反编译后的 .gml 文件
  • embeddedtexture → PNG 文件

输入:

{"dataFilePath": "data.win", "entityType": "sprite", "name": "sp_default_actor_sprite", "outputPath": "C:/out"}

返回:

{"success":true,"exportedFrames":1,"outputDir":"C:/out"}

utmt-search

跨所有类型按名称模式搜索实体。不区分大小写的子串匹配。

参数:

  • dataFilePath(必填)
  • query(必填)— 搜索关键字
  • entityTypes(可选)— 限定搜索类型(空 = 全部)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "query": "player", "entityTypes": ["gameobjects", "sprites"]}

返回(节选):

[{"type":"gameobject","index":6,"name":"o_00_movieplayer"},{"type":"gameobject","index":734,"name":"obj_player_actor"},{"type":"sprite","index":661,"name":"sp_2023res_playerwindow"},"..."]

utmt-get-room-assets

获取一个房间内使用的所有资源:精灵(含尺寸及使用它们的对象)、对象(含位置和精灵)、代码条目(来自事件)以及图层汇总。

参数:

  • dataFilePath(必填)
  • roomName(必填)— 房间名称(如 scene_gameplay
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "roomName": "betweenspace"}

返回:

{"room":"betweenspace","width":320,"height":180,"sprites":[],"objects":[{"name":"o_chromatest","sprite":"","depth":0,"visible":true,"x":0,"y":0,"instanceId":100000}],"codeEntries":[{"obj":"o_chromatest","evt":"create","subtype":0,"code":"gml_Object_o_chromatest_Create_0"},{"obj":"o_chromatest","evt":"draw","subtype":0,"code":"gml_Object_o_chromatest_Draw_0"}],"layers":[{"name":"Instances","type":2,"depth":0,"visible":true,"objectCount":1},{"name":"Background","type":1,"depth":100,"visible":true,"objectCount":0}]}

utmt-search-strings

按内容搜索字符串表。字符串没有名字,常规 utmt-search(按名字)搜不到它们。返回匹配的字符串索引和内容(每条截断到 500 字符)。

参数:

  • dataFilePath(必填)
  • query(必填)— 不区分大小写的内容搜索关键字
  • limit(可选)— 最大返回数(默认:50)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "query": "CoroutineThen", "limit": 3}

返回:

[{"index":287,"content":"THEN"},{"index":288,"content":"gml_Script___CoroutineThen"},{"index":289,"content":"__CoroutineThen"}]

utmt-export-all

批量导出某类型的全部资源到目录。支持:spritessoundsembeddedtextures。精灵导出为每个精灵一个 PNG 帧子目录,声音为 ogg/wav 文件,内嵌纹理为编号 PNG。返回导出/失败数量。

参数:

  • dataFilePath(必填)
  • entityType(必填)— 可选值:spritessoundsembeddedtextures
  • outputDir(必填)— 导出目标目录
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "entityType": "sounds", "outputDir": "C:/audio"}

返回:

{"type":"sounds","exported":664,"failed":[]}

utmt-get-object-code

反编译对象上某个事件的 GML 代码。返回 JSON,包含对象名、事件类型、子类型和反编译代码。子类型是零基索引:alarm 是闹钟编号;step 0=begin/1=normal/2=end;collision 是另一对象索引;其余映射到事件专属按键。单条目事件用 0(如 create)。YYC 编译的游戏不可用。

参数:

  • dataFilePath(必填)
  • objectName(必填)— 对象名(如 o_player
  • eventType(必填)— 可选值:createdestroyalarmstepcollisionkeyboardmouseotherdrawkeypresskeyreleasetriggercleanupgestureprecreate
  • subtype(可选)— 零基事件子类型索引(默认:0)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "objectName": "cc", "eventType": "create", "subtype": 0}

返回(code 字段为反编译的 GML,节选):

{"objectName":"cc","eventType":"create","subtype":0,"codeName":"gml_Object_cc_Create_0","code":"if (global.op_hide_cursor)\n{\n    window_set_cursor(cr_none);\n}\nglobal.gamefps = @@array_get@@([30, 60, 75, 90, 120, 144, 165, 240, 500, 1000], global.op_fpscap);\n...\ninstance_create_depth(0, 0, -1000, obj_judgement_display);\n"}

utmt-find-references

查找某个资产的引用。sprite:哪些对象使用它作为精灵、哪些房间包含这些对象的实例;object:哪些房间实例化它、哪些对象继承它;variable/function:哪些代码条目引用了它(扫描字节码指令);string:传入字符串索引,查找推入该字符串的代码条目。返回 JSON。

参数:

  • dataFilePath(必填)
  • type(必填)— spriteobjectvariablefunctionstring
  • name(必填)— 资产名(string 类型传索引)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "type": "variable", "name": "x"}

返回(节选):

{"codeReferences":[{"code":"gml_GlobalScript_create_chapter2_event_nodes","references":52},{"code":"gml_GlobalScript_create_chapter2end_event_nodes","references":16},{"code":"gml_GlobalScript_create_chapter3_event_nodes","references":57},...]}

utmt-find-unknown-functions

列出未被任何脚本、代码条目、内置函数或扩展函数解析的函数条目(缺失脚本、外部 DLL 函数、YYC 隐藏函数)。反混淆和完整性审计用。

参数:

  • dataFilePath(必填)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win"}

返回:

[]

utmt-extract-embedded-data

从 YYC 编译的可执行文件或内存 dump 中提取内嵌的 GameMaker 数据文件。扫描输入二进制中的 FORM+GEN8 头,把恢复的数据文件(data.win)写入输出路径。纯字节扫描,无需 UndertaleModCli。

参数:

  • dataFilePath(必填)— YYC 可执行文件或 dump
  • outputPath(必填)— 输出数据文件路径

输入:

{"dataFilePath": "game.exe", "outputPath": "extracted.win"}

返回:

{"success":true,"file":"extracted.win","offset":125952,"size":25165824,"candidates":1}

utmt-dead-resource-analysis

分析哪些字符串、变量、函数未被使用(没有被任何资产名或代码指令引用)。返回 JSON,含各分类总数和样本。内置变量/函数已排除。字符串检查还能发现未本地化的残留文本。

参数:

  • dataFilePath(必填)
  • limit(可选)— 每类样本上限(默认:50)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "limit": 3}

返回(节选):

{"unusedStrings":{"total":1552,"sample":[{"index":41466,"content":"@@SleepMargin"},{"index":41467,"content":"@@DrawColour"},{"index":41468,"content":"4294967295"}]},"unusedVariables":{"total":4844,"sample":[{"index":0,"name":"prototype"},{"index":1,"name":"@@array@@"},{"index":2,"name":"arguments"}]},"unusedFunctions":{"total":0,"sample":[]}}

utmt-find-replace

在全部代码条目中查找并替换文本(或正则),然后重新编译。写操作:结果保存到新的输出文件,原始文件绝不被修改。仅适用于 VM 编译的游戏(非 YYC)。

参数:

  • dataFilePath(必填)— 输入数据文件
  • outputFilePath(必填)— 输出文件(必须与输入不同)
  • find(必填)— 查找文本(或正则)
  • replace(必填)— 替换文本
  • caseSensitive(可选)— 区分大小写(默认:false)
  • isRegex(可选)— 按正则处理(默认:false)
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "outputFilePath": "data-mod.win", "find": "mod_scrollspeed", "replace": "mod_speed"}

返回:

{"success":true,"searched":4842,"message":"Find/replace applied; changes are saved to the -o output file"}

utmt-export-strings-json

将字符串表全部导出为 JSON 文件。用于本地化、词频分析、文本资产审计。

参数:

  • dataFilePath(必填)
  • outputPath(必填)— 输出 JSON 路径
  • cliPath(可选)

输入:

{"dataFilePath": "data.win", "outputPath": "strings.json"}

返回:

{"success":true,"file":"strings.json","count":51933}

支持的数据文件格式

  • data.win — Windows
  • game.ios — iOS
  • game.droid — Android
  • game.unx — Linux/macOS

开发

git clone <repo>
cd utmt-mcp
pnpm install
pnpm run build

测试

npm test

单元测试零依赖(Node 内置 node --test),校验所有脚本生成器的 null 安全、转义和结构。集成测试会真实调用 UndertaleModCli:对一个生成的空白数据文件跑全部工具脚本(覆盖 GM 1.x 空集合路径);如需对真实数据文件再跑一遍,设置 UTMT_TEST_DATA_WIN 环境变量指向 data.win(未设置则跳过真实文件用例)。集成测试需要 UTMT_CLI_PATH(或 PATH 中能找到 UndertaleModCli);CLI 缺失时对应用例自动跳过。

许可证

MIT