noita-data
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@noita-data what's the spell bundle for POLLEN?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
mcp-noita-data
把 Noita 解包后的 data/ 目录以 只读 MCP 工具暴露给模型。
只做数据获取,不做计算:不执行 Lua、不推导法术属性、不解析图片内容, 只负责把磁盘上的 XML / Lua / 文本原样读出来。
工具
工具 | 作用 |
| 列出目录直接子项(名称、路径、类型、大小、扩展名) |
| 按行读取文本文件,返回总行数以便翻页 |
| 解析 XML 为嵌套字典(属性平铺、同名子节点转数组) |
| 在文本内容中检索,返回文件 + 行号 + 行内容;有译文时支持中文查询 |
| 在译文表里互查: |
| 把一个法术在 |
| 一次汇总:卡牌字段 + 全部组件(合并 |
| 读取任意实体,合并一层 |
路径统一使用游戏内写法,data/ 前缀可省略:
data/scripts/gun/gun_actions.lua
scripts/gun/gun_actions.lua # 等价Related MCP server: obsidian-mcp
安装与运行
uv sync
uv run noita-data-mcp --data-dir ./data默认按以下顺序查找数据目录:
环境变量
NOITA_DATA_DIR当前工作目录下的
data/仓库根目录下的
data/
客户端配置
{
"mcpServers": {
"noita-data": {
"command": "uv",
"args": [
"run", "--directory", "C:/Users/dynas/Documents/Code/mcp-noita-data",
"noita-data-mcp", "--data-dir", "C:/Users/dynas/Documents/Code/mcp-noita-data/data"
]
}
}
}设计说明
路径隔离:所有路径先
resolve()再校验是否位于数据根之下,..与绝对路径一律拒绝。只读:没有任何写盘操作;文件系统权限交给操作系统。
不预扫描:4,000+ XML、1,000+ Lua 全部按需读取,避免启动时全量索引。
返回有上限:
read_text按行分页,read_xml按节点数截断并标记_truncated,search默认最多 50 条,避免单次结果撑爆上下文。二进制识别:按扩展名 + NUL 字节双重判断,图片/音频不会被当作文本读出。
UTF-8:启动时把 stdin/stdout 强制为 UTF-8,避免 Windows 控制台 GBK 破坏 JSON-RPC。
返回示例
read_text("scripts/gun/gun_actions.lua", offset=1, limit=2){
"path": "data/scripts/gun/gun_actions.lua",
"total_lines": 11126,
"start_line": 1,
"end_line": 2,
"lines": ["dofile_once(\"data/scripts/gun/procedural/gun_action_utils.lua\")",
"dofile_once(\"data/scripts/lib/utilities.lua\")"],
"truncated": true
}结构
src/noita_data/
├─ paths.py # data/xxx -> 绝对路径,越界与盘符一律拒绝
├─ text.py # 编码嗅探、二进制判定、按行分页
├─ xmljson.py # XML -> 嵌套字典(多根兜底、节点预算)
├─ search.py # glob + 正则/子串检索
└─ server.py # MCP 工具与入口本地化(translations)
译文来自 Noita 原生的 data/translations/*.csv(形如 "$action_light_bullet","火花弹")。
放进去即生效,也可以用环境变量指定:
set NOITA_TRANSLATIONS=D:\path\to\common.csv # 或一个目录有译文表时:
search("火花弹")会先反查成$action_light_bullet再搜,命中行附带translations;translate("火花弹")返回对应 key,translate("$action_light_bullet")返回译文;没有译文表时两者安全降级,只是不能按中文查。
当前这份 dump 不含 data/translations/,所以开箱只能用 id 搜索。
开发
uv run pytest # 10 个用例,覆盖路径、分页、XML、检索示例:复刻一个法术需要什么
spell_bundle("POLLEN") 一次返回整条链(节选):
{
"card": {"mana": "10", "price": "110", "spawn_level": "0,1,3,4",
"action_effects": ["c.fire_rate_wait = c.fire_rate_wait + 2",
"c.spread_degrees = c.spread_degrees + 20"]},
"projectiles": [{
"body": {"damage": "0.2", "lifetime": "750", "speed_min": "150", "speed_max": "250"},
"velocity": {"gravity_y": "10", "air_friction": "2.8", "mass": "0.35"},
"homing": {"homing_targeting_coeff": "10.0", "homing_velocity_multiplier": "0.89"},
"particles": [{"material": "spark_white", "color": "7fFEFEFF", "glow": "90"}],
"sprite": {"animation": {"frame_count": "4", "frame_width": "11", "frame_wait": "0.09"}},
"audio": {"event_root": "player_projectiles/bullet_arrow"}
}],
"not_available": ["贴图像素", "音频采样", "引擎侧公式(追踪/碰撞/伤害换算)"]
}数值来自 gun_actions.lua → related_projectiles → 实体 XML(合并一层 <Base>)→
materials.xml 的材质颜色 → projectiles_gfx/*.xml 的帧定义。全部只读。
同一法术的多份定义
scripts/gun/ 下有多张法术表(普通 / 有限法术 / 无限 / petri),字段并不相同。
spell("LIGHT_BULLET") 会把这些表里的条目并列列出(含行号区间):
_gun_actions_unlimited.lua L1052-1067 mana=5 price=- max_uses=- name="Spark bolt"
gun_actions.lua L43-63 mana=5 price=100 max_uses=- name="$action_light_bullet"
gun_actions_limited.lua L1146-1162 mana=5 price=- max_uses=100 name="Spark bolt"
gun_actions_petri.lua L1146-1162 mana=5 price=- max_uses=- name="Spark bolt"
gun_actions_unlimited.lua L1052-1067 mana=5 price=- max_uses=- name="Spark bolt"它按源码文本解析,不执行 Lua;要读函数体就用返回的 source 区间再 read_text。
范围
明确不做的事情:执行 Lua、计算法术派生数值、切分图集、渲染图片。 需要这类派生数据时应当在调用方完成,或另建一个构建期脚本,而不是塞进 MCP 工具。
致谢
Design inspired by Noita_Lib (GPL); no code copied.
Available Tools
8 toolsentityB
读取任意实体 XML,合并一层 ,返回它的全部组件。
组件不做筛选(Projectile / DamageModel / Homing / ParticleEmitter … 都保留), 适合自己实现行为逻辑时逐个组件取值。
Inputs: path (required). Returns: object
list_dirA
列出 data/ 下某个目录的直接子项(不递归)。
返回每一项的名称、游戏内路径、类型、大小与扩展名,用于定位文件。
Inputs: path. Returns: object
read_textA
按行读取一个文本文件(xml / lua / txt / csv 等)。
offset 为 1 起始行号,limit 为最多返回行数; 返回 total_lines 便于继续翻页。二进制文件会被拒绝。
Inputs: path (required), limit, offset. Returns: object
read_xmlB
把 XML 解析成嵌套字典返回。
属性直接平铺为键;同名子节点合并成数组;文本放在 "_text"。 max_nodes 限制节点总数,超出部分标记 "_truncated"。
Inputs: path (required), max_nodes. Returns: object
searchA
在文本文件内容中搜索(默认忽略大小写)。
query 为子串;regex=True 时按正则解释。存在译文表时, query 会先反查成 $key 一起匹配(可直接搜中文),命中行附带译文。 glob 用于缩小范围,例如 "/*.lua"、"scripts//*.xml"。 返回命中的文件、行号与行内容。
Inputs: query (required), glob, regex, max_results, +1 more. Returns: object
spellA
把一个法术在 scripts/gun/gun_actions*.lua 各版本表里的条目并列返回。
只解析源码文本,不执行 Lua、不做取舍:每个版本给出字段与行号区间, 需要看函数体时再用 read_text 按行区间读取。
Inputs: spell_id (required), max_tables. Returns: object
spell_bundleA
一次性汇总一个法术的数值:卡牌字段 + 投射物实体 + 特效 + 音效。
会自动跟随 related_projectiles、合并一层 、查 materials.xml 的粒子颜色、 读取 SpriteComponent 指向的图集帧定义。只读,不执行 Lua、不做换算。 拿不到的东西列在 not_available 里(贴图像素、音频采样、引擎公式)。
Inputs: spell_id (required). Returns: object
translateA
查询本地化词条:给 key 返回译文,给译文返回 key。
数据来自 data/translations/*.csv;文件不存在时 available=False, 此时搜索仍然可用,只是不能按中文等译文反查。
Inputs: text (required), limit. Returns: object
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
Loading tool schema changelog…
TDQS
Scored across 8 tools
Most tools have clearly distinct purposes (directory listing, raw text read, XML parse, search, translation, entity read). There is mild overlap between spell / spell_bundle (both about spells, though one returns aggregated numbers and the other Lua source entries) and between entity / read_xml (both read entity XML), but the descriptions clarify the boundaries well enough.
A partial verb_noun pattern exists (list_dir, read_text, read_xml), but it is broken by bare nouns (entity, spell) and noun compounds (spell_bundle), plus a bare verb (search, translate). Mixed conventions but each name is still readable and unambiguous.
Eight tools is well-scoped for a read-only data-inspection server, and each tool covers a distinct layer (listing, raw IO, parsing, search, localization, domain-specific aggregation). No redundant or filler tools.
The surface covers the core read-only lifecycle: locate files, read raw text, parse XML, search content, resolve translations, and domain-specific entity/spell inspection. Minor gaps like a spell/entity index or bulk listing exist but search plus list_dir let agents work around them.
Maintenance
Related MCP Connectors
Read-only MCP for the Eco game wiki: search, Markdown pages, and wiki_* lookups. No keys, no writes.
Search MCP servers, MCP clients and AI agents, and retrieve listing details. Free, read-only access.
Agent-native MCP server over the public saagarpatel.dev corpus. Read-only, stateless.
Public read-only MCP server for Genvernium product and developer resources.
Related MCP Servers
- FlicenseAqualityDmaintenanceEnables listing, reading, and searching local files and directories through MCP tools.4-
- AlicenseAqualityDmaintenanceProvides read-only access to an Obsidian vault, enabling file listing, content reading, and text search across notes via MCP.42Apache 2.0
- AlicenseNot gradedqualityDmaintenanceEnables safe, read-only browsing of allowlisted local directories through MCP, providing tools to list roots, read files, and search text.MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI clients to search and read a folder of Markdown/text documents via a read-only MCP server with hybrid BM25 and local embedding search, treating the calling model as untrusted.7 npmMIT