A bracket engine you can call
Five formats for any field size, with byes, seeding and the grand final reset handled properly. Run it as a library, hit it over HTTP with no account, or hand it to an LLM.
Try it
This calls the public endpoint below — nothing is stored.
From a terminal
No account, no network once installed.
npx @bracketintel/cli new "Ann,Bo,Cy,Di" npx @bracketintel/cli new -n 32 --format de npx @bracketintel/cli new --from teams.txt --format de --randomize --seed friday --svg
From an LLM
The same binary is an MCP server. Four tools, no authorization needed — a bracket is computed from its inputs, so nothing here touches your data.
{
"mcpServers": {
"bracketintel": {
"command": "npx",
"args": ["-y", "@bracketintel/cli", "mcp"]
}
}
}explain_formathow many rounds, matches and byes a field will producecreate_bracketbuild a bracket from a list of namesreport_resultrecord a winner and see the updated bracketnext_matcheswhich matches are playable right now
Over HTTP
Stateless and cacheable. Identical input always returns identical output, so responses are safe to cache indefinitely.
curl -X POST https://www.bracketintel.com/api/v1/engine/generate \
-H 'Content-Type: application/json' \
-d '{"format":"DOUBLE_ELIM","participants":["Alice","Bob","Carol","Dave"]}'Also /api/v1/engine/apply to report a result and /api/v1/engine/render for text, JSON or SVG. Full schema at /api/v1/openapi.json.
As a library
Pure and dependency-free, so an agent can skip tool calls and just write code against it.
import { generate, apply, renderText } from "@bracketintel/engine";
const bracket = generate({
format: "DOUBLE_ELIM",
participants: [{ id: "a", name: "Ann" }, { id: "b", name: "Bo" }],
});
console.log(renderText(bracket));How it models a bracket
A match declares where each of its two occupants comes from, rather than pointing forward at the match it feeds:
{ "id": "L2.1",
"slotA": { "kind": "winner", "matchId": "L1.1" },
"slotB": { "kind": "loser", "matchId": "W2.1" } }One shape covers an elimination tree, a losers bracket, group standings and a Swiss round that has not been paired yet. It is also what makes double elimination expressible at all: a loser edge has nowhere to live in a model built on “next match” pointers.