open-leagues

Migrate a league

Each source becomes one import pack: teams, managers, slots, scoring, rosters, weeks. Preview the pack, then commit it.

Pick a source

Paste or file is the fallback when a connect fails or the platform is unsupported.

SourcePreviewCommit
SleeperpreviewImportimportLeague
ESPNpreviewEspnimportEspn
Paste, PDF, screenshot recappreviewRebuildimportRebuild

Sleeper import takes a league id. findSleeperUser turns a username into that person’s leagues for a season; it is not an input to the import.

MCP · arguments
findSleeperUser  { "query": "ryan" }

previewImport    { "sleeperId": "<league id>", "includeHistory": false }

importLeague     { "sleeperId": "<league id>",
                   "claimRosterId": 4,
                   "includeHistory": false,
                   "confirm": true }

confirm: true is an MCP-layer gate, not part of the server function signature. Dispatch refuses the call without it.

Preview, then commit

The preview writes nothing. Every write happens inside one committer, so a failed import leaves no half league.

Never invent manager emails. No source API gives a verified one, and the committer has no email column. The commissioner types the allowlist in settings after import; managers attach to a seat with claimRoster.

addAllowlistEmail is app-only: in the catalog, not on the MCP allowlist.

After the commit

Committing writes your user id as commish_id. From then on the season runs here: waivers, trades, the book, the clock.

exportLeague gives a commissioner a JSON snapshot. Nothing reads one back in, and nothing writes to the platform you left.

Migration also runs as a playbook: say “bring over my Sleeper league” to an agent with open-leagues-migrate installed. It stops for your yes before the commit. See Playbooks.