Skip to main content
Glama
quickstraw

umdgencli-mcp

README.md
# UMDGenCLI MCP Server

An MCP (Model Context Protocol) server that lets AI agents drive
[UMDGenCLI](https://github.com/quickstraw/UMDGenCLI) — the command-line tool for
creating and editing PSP UMD images (ISO / CSO / DAX). Every major function of
UMDGenCLI is exposed as a dedicated tool, so agents can build compilations,
save images, convert formats, patch, extract, and inspect without learning the
CLI syntax.

## Requirements

- Node.js 18+ (developed and tested on Node 22 / Windows)
- The UMDGenCLI executable (`umdgen-win-x64.exe` / `umdgen-win-x86.exe` /
  `umdgen.exe`), from the [GitHub Releases page](https://github.com/quickstraw/UMDGenCLI/releases)

## Setup

```powershell
npm install
npm run build   # compiles TypeScript into dist/
```

## Installing from npm (other PCs)

The server is published as the `umdgencli-mcp` npm package. On any machine with
Node.js, install it globally (or use `npx`), then point an MCP client at the
`umdgen-mcp` binary with the `UMDGENCLI_PATH` env var set to that machine's
UMDGenCLI executable:

```powershell
npm install -g umdgencli-mcp
```

```json
{
  "mcpServers": {
    "umdgencli": {
      "command": "umdgen-mcp",
      "env": {
        "UMDGENCLI_PATH": "C:\\tools\\umdgen.exe",
        "UMDGENCLI_CWD": "C:\\workspace\\psp-images"
      }
    }
  }
}
```

No local build or install step is needed — the published package contains the
compiled server (`dist/`). The UMDGenCLI executable itself is not bundled; it
must exist on the target machine (it's self-contained, so no .NET runtime is
needed there either).

## Configuration

The server is configured entirely through environment variables:

| Variable | Required | Default | Description |
|---|---|---|---|
| `UMDGENCLI_PATH` | **yes** | — | Path to the UMDGenCLI executable. The server refuses to start without it. |
| `UMDGENCLI_STATE_FILE` | no | `<cwd>/.umdgen-mcp/umdgen.state` | Path of the persistent compilation state file. UMDGenCLI keeps the in-memory compilation (folder/file tree + volume metadata) in this file between invocations, so a compilation can be built up across many tool calls. |
| `UMDGENCLI_CWD` | no | server working directory | Working directory for the CLI subprocess. Relative paths in tool arguments (source files, output images) resolve against this. |

The server starts the CLI as a subprocess per tool call with `--state <file>`
prepended automatically. Call `umdgen_reset_session` to discard the current
compilation, and `umdgen_get_session` to see the active configuration.

## Registering with an MCP client

### Claude Desktop (`claude_desktop_config.json`)

```json
{
  "mcpServers": {
    "umdgencli": {
      "command": "node",
      "args": ["H:\\path\\to\\UMDGenCLI MCP\\dist\\server.js"],
      "env": {
        "UMDGENCLI_PATH": "H:\\path\\to\\umdgen.exe",
        "UMDGENCLI_CWD": "H:\\workspace\\psp-images"
      }
    }
  }
}
```

### Kilo (`kilo.json`)

```json
{
  "mcp": {
    "umdgencli": {
      "type": "stdio",
      "command": "node",
      "args": ["H:/path/to/UMDGenCLI MCP/dist/server.js"],
      "env": {
        "UMDGENCLI_PATH": "H:/path/to/umdgen.exe",
        "UMDGENCLI_CWD": "H:/workspace/psp-images"
      }
    }
  }
}
```

### Cursor / generic

Any client that supports `stdio` MCP servers works the same way: run
`node <path-to-repo>/dist/server.js` with the environment variables above.

## Tools

All tools are prefixed with `umdgen_` (per MCP naming conventions, to avoid
collisions with tools from other MCP servers). All tools return the CLI's
stdout/stderr plus the process exit code; a non-zero exit code is surfaced as
an error result (`isError: true`). Every tool carries MCP annotations
(`readOnlyHint`, `destructiveHint`, `idempotentHint`, `openWorldHint`) so
clients can show accurate approval prompts — e.g. `umdgen_set_version` is
marked destructive when patching in place, and `umdgen_reset_session` /
`umdgen_new_compilation` discard unsaved work. Outputs longer than 25,000
characters are truncated with a message telling the agent how to narrow the
result.

### Session & environment

| Tool | Description |
|---|---|
| `umdgen_get_session` | Show executable path, state file, working directory |
| `umdgen_reset_session` | Delete the state file and start a fresh compilation |
| `umdgen_get_version` | Print the UMDGenCLI version |
| `umdgen_get_help` | Show help (optionally for one command) |
| `umdgen_run_raw` | Escape hatch: run any command with raw arguments |

### Compilation building

| Tool | CLI equivalent |
|---|---|
| `umdgen_new_compilation` | `new` (label, padding, pad, no-pathtables, date) |
| `umdgen_open_image` | `open <image>` |
| `umdgen_add_file` | `add-file <src...> [--to <dir>]` |
| `umdgen_add_folder` | `add-folder <src...> [--to <dir>]` |
| `umdgen_new_folder` | `new-folder <name> [--to <dir>]` |
| `umdgen_rename_item` | `rename <path> <newname>` |
| `umdgen_delete_items` | `delete <path...>` |
| `umdgen_hide_items` / `umdgen_unhide_items` | `hide` / `unhide <path...>` |
| `umdgen_dummy_items` | `dummy <path...>` |
| `umdgen_dummy_search` | `dummy-search [image]` |
| `umdgen_optimize_image` | `optimize [image]` |
| `umdgen_relink_files` / `umdgen_relink_source` | `relink` / `relink-source` |
| `umdgen_move_lba` | `move-lba <file> <lba>` |
| `umdgen_set_label` | `set-label <label>` |
| `umdgen_set_date` | `set-date <yyyy-MM-dd>` |
| `umdgen_gen_umddata` | `gen-umddata [path]` |

### Display

| Tool | CLI equivalent |
|---|---|
| `umdgen_list_contents` | `list [image]` |
| `umdgen_show_tree` | `tree [image]` |
| `umdgen_show_props` | `props [image]` |

### Image operations

| Tool | CLI equivalent |
|---|---|
| `umdgen_image_info` | `info <image>` |
| `umdgen_dump_sfo` | `sfo <image>` |
| `umdgen_set_version` | `set-version <image> <version> [--out]` |
| `umdgen_save_image` | `save <out>` (+ format, level, nc, padding, pad) |
| `umdgen_extract_image` | `extract <image> <outdir> [paths...]` |
| `umdgen_convert_image` | `convert <in> <out>` (+ format, level, nc) |
| `umdgen_batch_convert` | `batch <outdir> <iso\|cso\|dax> <images...>` |
| `umdgen_apply_ppf` | `ppf-apply <image> <patch.ppf> [--file] [--out]` |
| `umdgen_export_iml` / `umdgen_import_iml` | `iml-export` / `iml-import` |
| `umdgen_create_image` | `create <dir> <out>` (one-shot build from a folder) |
| `umdgen_verify_image` | `verify <image>` |

## Agent workflow example

```
umdgen_get_session                    # confirm executable + state file
umdgen_reset_session                  # start clean
umdgen_new_compilation { label: "GAME001", padding: "umd" }
umdgen_new_folder { name: "PSP_GAME" }
umdgen_new_folder { name: "SYSDIR", to: "PSP_GAME" }
umdgen_add_file { src: ["EBOOT.BIN"], to: "PSP_GAME/SYSDIR" }
umdgen_add_file { src: ["PARAM.SFO"], to: "PSP_GAME" }
umdgen_list_contents                  # review the compilation
umdgen_save_image { out: "GAME001.iso", padding: "umd" }
umdgen_image_info { image: "GAME001.iso" }  # inspect the result
umdgen_convert_image { input: "GAME001.iso", output: "GAME001.cso" }
```

## Notes

- **Paths**: relative paths in tool arguments resolve against
  `UMDGENCLI_CWD` (or the server's working directory). Agents should prefer
  absolute paths for source files and outputs.
- **`add-file` reads source data at save time**: the on-disk source files must
  still exist when `save_image` runs.
- **`iml-import` only relocates existing files**: open the image (or build the
  compilation) first, then import the IML to apply the listed LBA layout.
- **`set-version` and `ppf-apply` require raw ISOs**; CSO/DAX inputs are
  rejected by UMDGenCLI itself.
- **`--padding umd`** reproduces UMDGen v4.00's output byte-for-byte; the
  default is no padding.

## Tests

`test/run-tests.mjs` is an end-to-end suite that spawns the server over stdio,
builds a compilation from generated fixtures (including a valid PARAM.SFO),
and exercises every tool against a real UMDGenCLI executable:

```powershell
$env:UMDGENCLI_PATH = "H:\path\to\umdgen.exe"
node test\run-tests.mjs
```

## Evaluation

`test/evaluation.xml` contains 10 read-only, independent, verifiable questions
designed to measure how well an agent can use the server with no other
context. The corpus is deterministic:

```powershell
$env:UMDGENCLI_PATH = "H:\path\to\umdgen.exe"
npm run eval:fixtures   # builds test/eval/work/eval1.iso, eval2.iso, eval2.cso
npm run eval:verify     # solves all 10 questions through the server; asserts answers
```

To run the questions through an LLM harness (requires Python 3.10+ and an
`ANTHROPIC_API_KEY`), point it at the server with the working directory set to
`test/eval/work` so the relative image paths in the questions resolve. Any
standard MCP evaluation harness works — for example the one shipped with the
`mcp-builder` skill (install its dependencies with `pip install anthropic mcp`
first) — run against this server as:

```powershell
python evaluation.py `
  -t stdio -c node -a dist/server.js `
  -e UMDGENCLI_PATH=H:\path\to\umdgen.exe `
  -e UMDGENCLI_CWD=test/eval/work `
  test/evaluation.xml
```