Skip to main content
Glama
seanpdwyer7

franchise-mcp-server

by seanpdwyer7
README.md
# franchise-mcp-server

An MCP (Model Context Protocol) server that lets LLMs read and edit **Madden NFL
franchise saves** and **EA SPORTS College Football dynasty saves (CFB 27+)**. It
wraps [bep713/madden-franchise](https://github.com/bep713/madden-franchise) — the
community-standard parser behind tools like Franchise Editor — and exposes its
full capability as a set of well-guarded tools. It also reaches the **Frostbite
game-asset layer** (textures/meshes/tuning inside the game files) via a headless
Frosty sidecar — see [Frostbite game-asset layer](#frostbite-game-asset-layer-frosty_-tools).

Supported games (inherited from the library): Madden 19–27, College Football 27+.
Both franchise saves and FTC (franchise-common) game-data files open.

```
┌────────────┐     MCP (stdio)     ┌─────────────────────┐        ┌──────────────────┐
│ LLM client │ ◄─────────────────► │ franchise-mcp-server │ ◄────► │ madden-franchise │ ◄── CAREER-* / DYNASTY-* files
└────────────┘                     └─────────────────────┘        └──────────────────┘
```

## Layout

```
franchise-mcp-server/
├── src/                 TypeScript source
│   ├── index.ts         server + tool registrations
│   ├── session.ts       open-file sessions, table resolution, field loading
│   ├── serialize.ts     field value ⇄ JSON conversion, validation, pagination
│   ├── types.ts         structural types for the library
│   └── constants.ts
├── dist/                built JS (entry: dist/index.js)
├── tests/smoke-test.mjs end-to-end test (drives the server over stdio)
└── skills/franchise-editor/          ← docs for LLM agents
    ├── SKILL.md                       main skill (workflow + safety rules)
    └── references/
        ├── domain-model.md            file anatomy, references, free-lists
        ├── workflows.md               step-by-step recipes
        ├── cfb-notes.md               CFB 27 dynasty specifics
        └── library-api.md             building apps on the library directly
```

## Setup

Requires **Node.js >= 22.19.0**.

This server depends on madden-franchise via `file:../madden-franchise` — clone it
as a **sibling directory** (the repo version includes CFB 27 support that is
ahead of the npm release):

```bash
# 1. Clone both repos side by side
git clone https://github.com/bep713/madden-franchise.git
git clone https://github.com/<you>/franchise-mcp-server.git

# 2. Build the library
cd madden-franchise && npm install && npm run build

# 3. Build the server
cd ../franchise-mcp-server && npm install && npm run build

# 4. Smoke test against bundled CFB 27 test data (uses a copy!)
cp ../madden-franchise/tests/data/DYNASTY-27COMPRESS /tmp/DYNASTY-TEST
node tests/smoke-test.mjs /tmp/DYNASTY-TEST
```

### Register with Claude Code (project `.mcp.json`)

```json
{
  "mcpServers": {
    "franchise": {
      "command": "node",
      "args": ["<absolute-path-to>/franchise-mcp-server/dist/index.js"]
    }
  }
}
```

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

```json
{
  "mcpServers": {
    "franchise": {
      "command": "node",
      "args": ["<absolute-path-to>/franchise-mcp-server/dist/index.js"]
    }
  }
}
```

Give the agent the `skills/franchise-editor/` folder (Claude Code discovers it
from `.claude/skills/`; other agents can be pointed at SKILL.md directly).

## Tool catalog

### File lifecycle
| Tool | Purpose |
|---|---|
| `franchise_open` | Open a CAREER-*/DYNASTY-* file into a session. Options: `auto_unempty` (needed to add rows), `game_year_override`, `game_type_override`. Returns game/schema info. |
| `franchise_save` | Persist changes — overwrite, or `output_path` to save-as. Nothing is written to disk without this. |
| `franchise_close` | Close a session, discarding unsaved changes. |
| `franchise_list_open_files` | Sessions + which tables have unsaved changes. |

### Discovery
| Tool | Purpose |
|---|---|
| `franchise_list_tables` | Browse/filter the ~2,000+ tables (name, uniqueId, record count, capacity, isArray). |
| `franchise_get_table_schema` | Field definitions: type, min/max, maxLength, enum members, reference-ness, storage section. |

### Reading
| Tool | Purpose |
|---|---|
| `franchise_read_records` | Paginated row reads with field selection; `row_indices` for specific rows; array tables return ordered reference lists. |
| `franchise_get_record` | Every field of one row, field-paginated (Player has ~300 fields). |
| `franchise_search_records` | Find rows by field conditions (`eq/neq/contains/gt/gte/lt/lte`), e.g. player by name. |

### Writing
| Tool | Purpose |
|---|---|
| `franchise_edit_records` | Batch field edits with validation: range-checked ints, length-checked strings, enum-name checking, references as `{tableId,row}`/`{tableUniqueId,row}`/null, JSON blobs (CharacterVisuals). Echoes old→new values. Blocks writes to empty records unless `auto_unempty`. |

### References & row lifecycle
| Tool | Purpose |
|---|---|
| `franchise_resolve_reference` | Decode 32-bit refs (binary string, asset id, or tableId+row) to table name/uniqueId/row. |
| `franchise_find_references_to_record` | Which tables point at a record (run before removing/repurposing anything). |
| `franchise_get_empty_records` | Free-list state: `nextRecordToUse`, empty-row chain — the safe way to add rows. |
| `franchise_recalculate_empty_records` | Rebuild the free-list after bulk operations. |

## Bundled full CFB 27 schema

CFB save headers only declare one of the game's three schema namespaces, so
stock schema selection leaves key tables (notably **Team**) schema-less. This
server bundles the full combined schema (`data/schemas/CFB27_809_0.gz`,
major 809) and auto-applies it to college saves — unlocking real field names
for team identity, the native Media/Coaches/CFP polls, prestige, and records.
Schema extraction method credit:
[brooksg357-a11y/cfb27-dynasty-modding](https://github.com/brooksg357-a11y/cfb27-dynasty-modding).

## Design notes

- **Validation-first writes.** The underlying library bit-packs values and will
  silently wrap out-of-range ints and corrupt free-lists if misused; this server
  rejects out-of-range/oversized/invalid-enum writes and empty-record writes
  with errors that state the valid values.
- **Stable identity.** Tools push agents toward `table_unique_id` (stable across
  files and game years) over file-specific `tableId`s and ambiguous names.
- **Context-efficient.** Everything is paginated and field-selectable;
  responses over ~25k chars truncate with explicit `truncated_by_size` +
  `next_offset` metadata.
- **Edit-safe partial reads.** Field lists load incrementally; pending edits are
  flushed to the table buffer before any re-read, so partial reads never lose
  unsaved changes.
- **Sessions.** Multiple files can be open at once (e.g. copy data between a
  Madden franchise and a CFB dynasty, or between a save and its backup).

## Known table uniqueIds

| Table | uniqueId | Verified |
|---|---|---|
| Player | `1612938518` | Madden 25/26, CFB 27 |
| CharacterVisuals | `1429178382` | CFB 27 |

Everything else: discover per-file with `franchise_list_tables` (name collisions
are common — eight tables named `Team` exist in CFB 27; pick by record count).

## Draft class files (CAREERDRAFT-*)

Three additional tools read and write Madden 25/26 shareable draft class
files directly (the CAREERDRAFT-* files the game imports/exports), separate
from franchise saves:

- **draftclass_read** — header + paginated prospects (~90 friendly fields
  each: names, all ratings, draft round/pick, dev trait, body type,
  portrait/commentary ids, college, full visuals JSON)
- **draftclass_get_prospect** — one prospect, everything, optional visuals
- **draftclass_edit_prospects** — apply field edits and write the file back
  (auto-backup when overwriting in place)

Powered by [madden-draft-class-tools](https://github.com/WiiExpertise/madden-draft-class-tools)
by **WiiExpertise** (GPL-3.0) — all credit for the CAREERDRAFT format work.

## Frostbite game-asset layer (`frosty_*` tools)

Everything above edits **save files**. Four more tools reach the **game's own
Frostbite asset database** — the EBX objects, textures, meshes and gameplay
tuning inside CFB 27 / Madden 26 themselves — by driving MMC/Frosty's
`FrostySdk` **headlessly**. Proven on a real CFB 27 install: **1,012,545 assets**
loaded, searched, and read into typed JSON.

- **frosty_info** — profile + total asset count
- **frosty_search_assets** — find assets by name (optional type filter)
- **frosty_list_types** — distinct asset types with counts (discovery)
- **frosty_read_asset** — one asset → full typed JSON tree

These are **opt-in**: set `FROSTY_MMC_PATH` to your MMC/Frosty editor folder
(after building the sidecar there — see [`frosty-cli/`](frosty-cli/)). Unset, the
tools error with a hint and the save tools are unaffected. The server keeps one
long-lived sidecar per game, so the first call loads the asset DB (~20s) and the
rest are instant.

```
┌────────────┐   MCP   ┌─────────────────────┐   stdin/stdout   ┌──────────────┐
│ LLM client │ ◄─────► │ franchise-mcp-server │ ◄──────────────► │ frosty-cli.exe│ ◄── CFB27 / M26 game data
└────────────┘         └─────────────────────┘  (headless SDK)  └──────────────┘
```

What's in there: gameplay/sim tunables live under `AttribSys/data/**`. Note that
**recruiting / NIL / dynasty logic is compiled, not in the asset layer** — the
asset DB only holds recruiting UI icons and cutscenes, so recruiting changes must
go through the save-file (`franchise_*`) tools. Read is proven; writing `.fbmod`
files is the next step. Build + boot recipe + honesty notes: [`frosty-cli/README.md`](frosty-cli/README.md).

## License

MIT (the wrapped madden-franchise library is MIT by matthewpanetta/bep713).