Local Codex MCP tools for converting, inspecting, and safely editing Neverwinter Nights 2 Enhanced Edition modules. Swordflight is the initial large-scale conversion project, but the file operations are module-agnostic.
The server uses the x64 SwordflightAudit.exe core in the game workspace. It
communicates over MCP stdio and does not listen on a network port.
- Neverwinter Nights 2 Enhanced Edition
- Windows with WSL (the currently tested environment)
- Node.js 18 or later
- 64-bit .NET Framework MSBuild for building the optional C# core
No game DLLs, campaign modules, HAK files, or converted assets are distributed in this repository.
From PowerShell:
.\scripts\build-core.ps1 -GameRoot "C:\Games\NWN2 Enhanced Edition"The build uses OEIShared64.dll from your own NWN2 installation. Set
coreExecutable in the local configuration to the resulting
core/SwordflightAudit/bin/x64/Release/SwordflightAudit.exe.
- Read operations are limited to the configured NWN2 game, remaster workspace, and user module roots.
- Writes are limited to the remaster workspace and user module root.
- Writes to a user module are refused while the NWN2 Toolset process is running. This prevents cached Toolset state from overwriting API changes.
- Every object transform and every overwritten resource is backed up before mutation.
- Whole-module backups protect area-geometry replacement before ARE/GIT/GIC/ TRN/TRX changes are committed.
- GFF object transforms are written through a temporary file and atomically replace the target GIT.
Copy config.example.json to config.local.json and set the five local paths.
config.local.json is ignored by Git. Alternatively set the equivalent
NW2_* environment variables listed in .mcp.json.
The server also checks ~/.config/nw2-toolchain/config.json, or a custom file
selected by NW2_TOOLCHAIN_CONFIG.
nw2_statusopen_module_in_toolsetsave_module_in_toolsetsave_and_close_toolsetaudit_moduleinspect_areareplace_area_geometryexport_tileset_layoutbackup_moduleensure_module_haksset_module_campaignbuild_hak_from_directorypack_moduleconvert_area_in_toolsetconvert_areas_in_toolsetplace_area_blueprintspaint_terrain_cellsset_object_transformset_object_linkmerge_resourcesbuild_area_pilotextract_converted_content
convert_area_in_toolset uses the companion x64 NWN1 Area Converter bridge
inside a running Toolset. The MCP side optionally creates a full milestone
backup when createBackup is true, submits a file-based local request, waits
for the Toolset UI thread to convert and save, then inspects the saved area.
The offline MCP remains the owner of backups, validation, manifests, and batch
orchestration.
convert_areas_in_toolset validates up to 32 reviewed ResRefs before writing,
and reuses the same open Toolset session to convert and save each area in
order. Ordinary batches default to no full-module backup. Set
createBackup: true for a deliberate milestone; pass its returned
backupPath as sessionBackupPath on later batches in the same development
session to reuse it. Reused backups are restricted to the configured backup
root and verified against their source-module metadata and module.ifo
checksum. They are also bound to the current Toolset process.
After a batch, only the new areas and the existing areas listed in
neighborAreaResRefs are inspected. The result includes object counts and a
scoped transition report; links whose destination is not among those inspected
areas are reported as target-outside-inspected-scope, not treated as a broken
global link. Run audit_module separately at milestones when a full-module
inventory is wanted. The batch stops on the first failure and reports the
number of completed areas and the session-baseline backup when one was
requested. Area-conversion targets
must be directory modules under the NWN2 user modules root because the legacy
converter resolves new-area paths relative to that location.
open_module_in_toolset, save_module_in_toolset, and
save_and_close_toolset manage a validated Toolset session without UI key
simulation. Opening launches the x64 Toolset and asks the installed bridge to
load the selected directory module on the UI thread. Saving audits and verifies
the saved result; createBackup: true additionally creates a full milestone
backup first.
Save-and-close waits for a clean process exit and never provides an
unsaved-discard path.
export_tileset_layout reads the NWN1 area tile IDs and the matching SET
metadata directly from a user-supplied HAK. It calibrates rotation by checking
tile adjacency and emits only identifiers and semantic relationships; it does
not extract or copy model, texture, minimap, or walkmesh payloads. This makes
custom NWN1 tilesets useful as private layout references while keeping their
art assets outside the NWN2 project and this repository.
place_area_blueprints sends a reviewed list of native NWN2 placeable
blueprints to the open Toolset module. Generated objects use a reserved Tag
prefix, making regeneration idempotent. The MCP side validates the open module,
creates a full backup, waits for Toolset to save, and verifies the generated
objects from disk.
paint_terrain_cells applies native NWN2 terrain texture ResRefs through the
open Toolset renderer at reviewed world-space cell centers. It validates local
texture availability, creates a full module backup, waits synchronously for the
renderer to save the TRN, and reports before/after hashes for disk verification.
replace_area_geometry reuses an existing unpacked NWN2 exterior area as a
geometry template. It copies the source ARE/TRN/TRX and static, non-usable
placeables, while retaining the target area's name, scripts, local area
properties, creatures, doors, encounters, items, interactive placeables,
sounds, stores, triggers, and waypoints. The operation is blocked while Toolset
is running and audits dimensions, terrain, and preserved object counts after
replacement. Full-module backup is opt-in with createBackup: true.
ensure_module_haks appends missing HAK dependencies to an unpacked module
without removing its existing entries. It verifies that each requested HAK is
installed, refuses writes while Toolset is running, and creates a full module
backup before updating MODULE.IFO.
set_module_campaign reads the GUID from a selected Campaign.cam, writes it
to the module Campaign_ID, and verifies the saved value. This lets a converted
module load campaign-scoped models, textures, 2DA files, and other resources
without copying those assets into the module directory.
build_hak_from_directory recursively flattens supported NWN2 resource files
from nested source folders into a V1.1 HAK. It rejects duplicate ResRef/type
pairs, writes atomically, and preserves an existing output in the backup
workspace before replacement.
set_object_link transactionally sets or clears a placed object's transition
link using explicit door, waypoint, or none target semantics. It is
intended for restoring links that the legacy converter omitted, and verifies
the saved LinkedTo and LinkedToFlags values from the area manifest.
For NWN1 exterior tilesets that are absent from the converter database, the bridge can ask Toolset to create a native flat exterior terrain area first, then migrate area metadata and placed objects into that terrain shell. Terrain height, walkmesh refinement, and Bake remain separate art and validation passes.
After configuring the local paths:
node scripts/smoke-test.mjsTo invoke one tool from a terminal while developing:
node scripts/call-tool.mjs nw2_status
node scripts/call-tool.mjs inspect_area '{"areaResRef":"shop002"}'The smoke test verifies MCP initialization, tool discovery, status, module
audit, area inspection, and the Toolset-running write guard. Optional isolated
write tests use NW2_MCP_WRITE_TEST_MODULE and
NW2_MCP_MERGE_TEST_SOURCE. Set NW2_MCP_PACK_TEST_OUTPUT as well to verify
packing a test directory module with the installed ModPacker.exe.
NW2 Toolchain is MIT licensed. See THIRD_PARTY.md for game library and asset boundaries.