MCP server
Connect claude.ai, ChatGPT, Codex, Claude Code, Claude Desktop, Cursor, VS Code or any Streamable HTTP MCP client to SETTO. Sign in with your SETTO account or use a personal or organization API token; 38 tools read your tournaments, set them up, register and replace teams, set up their groups and knockout draws, record results, schedule their games and show what changed.
SETTO publishes a remote Model Context Protocol
server at https://docs.setto.io/mcp. It exposes the External API as MCP
tools, so an assistant can answer "how many teams are in the Cuarta Fuerza
category?" by calling a tool instead of you pasting JSON into a chat, can set
a tournament up when you ask (create it, add its categories, register the
pairs, replace a player, withdraw a team), can set up its groups and its
knockout draw and record the results you report, and can lay out a day of group games on your
courts for you to approve. It accepts two
kinds of credential: your SETTO account, through a sign-in the app runs for
you (claude.ai, ChatGPT, Codex, Claude Code), or the same API token as the
REST API, personal or organization. Signed in, or with a personal token, the
assistant sees every tournament you manage; with an organization token, only
that organization's.
Endpoint
| Property | Value |
|---|---|
| URL | https://docs.setto.io/mcp |
| Transport | Streamable HTTP |
| Auth | Sign in with your SETTO account (OAuth), or Authorization: Bearer setto_live_… with a personal or organization API token |
| Access | Every call acts as one organizer — you when you signed in, a personal token's owner, or the admin who created an organization token — within the permissions granted. Reads need nothing more; setting tournaments up and drawing them needs «Gestionar torneos», recording results «Cargar resultados», applying a schedule «Programar partidos» |
| Registry name | io.setto.docs/mcp in the official MCP Registry (publication pending) |
The server is a thin proxy: it forwards each tool call to the External API with your credential and hands the JSON back. Anything the API refuses — a tournament you cannot reach, a write you did not allow — the MCP server refuses too. Every tool call asks the API again, so disconnecting an app, revoking a token or leaving an organization takes effect on the next call.
Install
There are two ways in:
- Sign in with your SETTO account — claude.ai, ChatGPT, Codex and Claude
Code. Nothing to create first: the app opens SETTO, you approve what it may do
at
app.setto.io, and it acts as you. claude.ai and ChatGPT connect only this way. - An API token — any client that sends a header: Claude Code, Codex, Claude Desktop, Cursor and VS Code. Cursor connects only this way.
Sign in with your SETTO account
In claude.ai open Customize → Connectors, choose + Add → Add custom
connector, paste https://docs.setto.io/mcp and sign in when claude.ai asks.
Every Claude plan can add custom connectors (one on Free); on Team and
Enterprise an owner adds it first. Claude Desktop uses the same connector.
The consent screen lists six permissions («Permisos») with every one the app asked for ticked: untick what you do not want to allow. You see and disconnect connected apps in Configuración → Conexiones. The whole flow, the permissions and troubleshooting are on Sign in with your SETTO account.
With an API token
Get a token first: in app.setto.io → Configuración → Tokens de API,
keep the scope on Personal (or pick an organization) and create one; under
Permisos, tick «Gestionar torneos» if the assistant should set
tournaments up (their categories, groups and draws too),
«Cargar resultados» if it should record and clear results, and
«Programar partidos» if it should place games.
Configuración → Conectar con IA walks through the same setup
and, right after you create a token there, shows each client's config with that
token already filled in. Without a token in place, the Cursor install connects to
nothing and says nothing.
Neither button carries your token. Cursor reads it from the
SETTO_API_TOKEN environment variable; VS Code asks for it once, masks it
and stores it. For Claude Code, use the plugin or the one-liner below; for
Codex and Claude Desktop, their tabs.
The plugin installs the MCP server and the setto-api skill
in one step, and updates both with claude plugin update.
claude plugin marketplace add https://docs.setto.io/claude-plugin/marketplace.json
claude plugin install setto@settoWhen the plugin is enabled, Claude Code asks for your SETTO API token in a
masked field and keeps it in your system's secure credential store, never in a
settings file. Start a session and run /mcp: setto should list 38 tools.
If your Claude Code is too old for plugin prompts, or you prefer the token in
your environment, use the one-liner in the next tab.
Tools
| Tool | Endpoint behind it | Writes? |
|---|---|---|
me | GET /v1/external/me | No |
list_tournaments | GET /v1/external/tournaments | No |
get_tournament | GET /v1/external/tournaments/{idx} | No |
list_divisions | GET /v1/external/tournaments/{idx}/divisions | No |
list_teams | GET /v1/external/tournaments/{idx}/teams | No |
get_round | GET /v1/external/rounds/{idx} | No |
get_schedule | GET /v1/external/tournaments/{idx}/schedule | No |
propose_pool_per_court_schedule | POST /v1/external/tournaments/{idx}/schedule/proposals | No — it computes a plan and saves nothing |
apply_schedule_placements | POST /v1/external/tournaments/{idx}/schedule/placements | Yes — game times, courts and lengths. Needs «Programar partidos» |
list_activity | GET /v1/external/activity | No — it reads «Actividad»: who changed what, through which app or token, and whether it went through |
search_tournament | GET /v1/external/tournaments/{idx}/search | No — finds categories, rounds, groups, teams and players by the name you say |
create_tournament | POST /v1/external/tournaments | Yes — a draft tournament on the FREE plan, with its categories. Needs «Gestionar torneos» |
update_tournament | PATCH /v1/external/tournaments/{idx} | Yes — name, dates, timezone, public link, visibility, who submits results |
publish_tournament | POST /v1/external/tournaments/{idx}/publish | Yes — publishes a draft when it is ready |
set_tournament_lifecycle | POST /v1/external/tournaments/{idx}/lifecycle | Yes — «Borrador de torneo», «Archivar», «Restaurar» |
create_division | POST /v1/external/tournaments/{idx}/divisions | Yes — adds a category |
update_division | PATCH /v1/external/tournaments/{idx}/divisions/{divisionIdx} | Yes — edits a category |
delete_division | DELETE /v1/external/tournaments/{idx}/divisions/{divisionIdx} | Yes — deletes a category with no teams and no games, after confirm: true |
set_division_seeds | PUT /v1/external/tournaments/{idx}/divisions/{divisionIdx}/seeds | Yes — «Cabezas de serie» |
register_team | POST /v1/external/tournaments/{idx}/registrations | Yes — registers one team; no email is sent |
register_teams | POST /v1/external/tournaments/{idx}/registrations/batch | Yes — registers up to 50 teams, each on its own |
update_team | PATCH /v1/external/tournaments/{idx}/teams/{teamIdx} | Yes — name, registration status, category |
remove_team | DELETE /v1/external/tournaments/{idx}/teams/{teamIdx} | Yes — deletes a team with no games and no group and no payment trace, after confirm: true |
update_player | PATCH /v1/external/tournaments/{idx}/players/{playerIdx} | Yes — a player's name, email or phone |
substitute_player | POST /v1/external/tournaments/{idx}/teams/{teamIdx}/substitute | Yes — «Sustitución»: one player out, another in |
preview_team_withdrawal | POST /v1/external/tournaments/{idx}/teams/{teamIdx}/withdraw/preview | No — shows what a «Baja» would do, game by game, and saves nothing |
withdraw_team | POST /v1/external/tournaments/{idx}/teams/{teamIdx}/withdraw | Yes — «Baja»: applies exactly the plan the preview showed |
preview_division_format | POST /v1/external/tournaments/{idx}/divisions/{divisionIdx}/format/preview | No — shows what a category's format («Formato») would keep and replace, and saves nothing |
apply_division_format | POST /v1/external/tournaments/{idx}/divisions/{divisionIdx}/format | Yes — applies exactly the format the preview showed. Needs «Gestionar torneos» |
append_elimination_round | POST /v1/external/tournaments/{idx}/divisions/{divisionIdx}/rounds/append | Yes — adds the knockout («Eliminatorias») after the group stage, keeping every group game |
preview_pools | POST /v1/external/tournaments/{idx}/rounds/{roundIdx}/pools/preview | No — «Configurar grupos»: the groups with their teams and games, and what they replace; saves nothing |
apply_pools | POST /v1/external/tournaments/{idx}/rounds/{roundIdx}/pools | Yes — writes exactly the groups the preview showed |
preview_draw | POST /v1/external/tournaments/{idx}/rounds/{roundIdx}/draw/preview | No — «Configurar eliminatorias»: the knockout's first round and what it replaces; saves nothing |
apply_draw | POST /v1/external/tournaments/{idx}/rounds/{roundIdx}/draw | Yes — writes exactly the draw the preview showed |
confirm_draw | POST /v1/external/tournaments/{idx}/rounds/{roundIdx}/draw/confirm | Yes — «Confirmar cuadro»: seats the teams the final group standings name. Sent again, it changes nothing |
record_game_result | POST /v1/external/tournaments/{idx}/games/{gameIdx}/result | Yes — a game's result: its sets, a W.O., a retirement or «Doble W.O.». Needs «Cargar resultados» |
clear_game_result | DELETE /v1/external/tournaments/{idx}/games/{gameIdx}/result | Yes — «Borrar resultado», after confirm: true. Needs «Cargar resultados» |
set_game_teams | PATCH /v1/external/tournaments/{idx}/games/{gameIdx}/teams | Yes — who plays a game that has no result yet. While a side is still a group place («1ro Pool A»), both sides of a first-round game at once, or «Confirmar cuadro» seats them; an emptied slot shows its label again |
Arguments mirror the parameters documented for each endpoint, including
populate, limit/offset, the division filter and list_activity's
cursor, which pages back from the newest row. Every tool states all
four MCP hints: the reads (the proposal and the four previews included)
are read-only, idempotent and non-destructive; a create (a tournament, a
category, a registration) is not idempotent, since calling it twice adds two;
an edit, a publish, the seeds, the knockout append and a result are idempotent
and non-destructive; a delete, the lifecycle, «Sustitución», «Baja», the
schedule write, applying a format, groups or a draw, «Confirmar cuadro», a
game's teams and clearing a result are destructive and idempotent; and none of
them reaches beyond your SETTO account (openWorldHint: false). Guides for the reads:
list tournaments,
get a tournament,
list divisions,
list teams, get a round.
Scheduling with an assistant
The assistant can fill a day of group games «un grupo por cancha»: each
group plays its games back to back on one court, parallel courts carry
different categories, the teams' time petitions decide each group's window, and
nobody is booked in two places at once — not even a player registered in two
categories. The proposal does not move games that are already scheduled; it
only places the unscheduled ones around them. Applying is different:
apply_schedule_placements can move any scheduled game that has not been
played yet, so it writes exactly the placements you approve.
It always goes in this order, and the server's instructions teach it to the model:
get_schedule— courts, categories, every game (and which ones are locked: played, scored or already started) and the approved petitions.propose_pool_per_court_schedule— a plan for one day. Nothing is saved. It lists the placements, any game it could not place, and every team it had to put outside a time it prefers.- You review it. The assistant shows you each court's games with their times, the unplaced games and the petition misses, and waits for your yes.
apply_schedule_placements— writes exactly what you approved. All or nothing: if anything would clash (a court, a team or a person twice at once, or a cannot play petition), nothing is written and the assistant gets the full list of offending games to show you.
The «Programar partidos» permission
Applying a schedule needs «Programar partidos» (schedule), one of the six
permissions («Permisos») a sign-in or a token can carry:
- Signed in with your SETTO account: leave «Programar partidos» ticked on SETTO's consent screen. The app then schedules any tournament you manage, for as long as you manage it.
- A personal token: tick «Programar partidos» under Permisos when you
create it in
app.setto.io→ Configuración → Tokens de API; the token list marks it «Programa partidos». It schedules any tournament you manage, for as long as you manage it. - An organization token with the permission can only be created by an
organization
ADMIN, and works only while that person is still anADMINof the organization.
Every other credential reads — including step 2, which writes nothing — and gets
403 INSUFFICIENT_SCOPE on step 4, which the assistant reports, with the fix for
its kind of credential, instead of retrying. A signed-in app gets the permission
by connecting again and leaving it ticked.
Use a read-only token, or untick «Programar partidos» when you sign in, wherever you only need answers, and keep a scheduling credential for the sessions where you plan days.
Setting a tournament up with an assistant
Ask in your own words — "create the Copa Primavera, padel, March 14 and 15 in Mexico City, with 4a varonil and 5a femenil", "register these eight pairs in 4a", "Luis Ruiz replaces Juan Pérez in his pair", "Pérez / Soto withdraw" — and the assistant turns it into the tools above. It creates tournaments on the FREE plan as a draft («Borrador»: 2 categories, 12 pairs or 24 singles), adds and edits categories and their seeds («Cabezas de serie»), registers teams one by one or up to 50 at a time, edits teams and players, replaces a player («Sustitución») and withdraws a team («Baja»). It publishes, takes back to draft, archives or restores a tournament only when you ask. Paid plans, prices, payments and fútbol tournaments stay in the dashboard.
The write contract
- Names become ids by reading first. The assistant finds the tournament,
category, team or player you name with
list_tournamentsandsearch_tournament. When two of the same kind fit (two players called Juan Pérez), the answer saysambiguousand the assistant asks you which one. - «Vista previa» before a withdrawal.
preview_team_withdrawalwrites nothing: it lists every game of the team and what the «Baja» does to it — a W.O. for a known rival, a pass («BYE») for a rival still to be decided, a placement game decided at once, or a game left as it is for you to record in the dashboard once its rival is known. Each game comes with that consequence in Spanish. The assistant shows you the list and waits for your yes. - Your yes is the confirmation.
withdraw_teamapplies exactly the plan you saw: it carries the preview's confirmation, valid 15 minutes, for that team and that plan. If the tournament changed in between, nothing is written and the assistant previews again. A category or a team is deleted only after your yes too (confirm: true), and only while it holds nothing: a team with games leaves through a «Baja», which keeps its played results. - A retry never writes twice. Every create and team operation carries an idempotency key, so a call repeated after a timeout answers the first result instead of creating a second tournament or registering a pair twice.
- Limits are yours to lift. A category or a team beyond what the plan holds is refused before anything is written, and the assistant tells you to upgrade in the dashboard («mejora el plan en el panel»). An organizer creates at most 20 tournaments a day through the API.
- Everything lands in «Actividad». Every write, and every refusal, is
recorded with who acted and through which app or token;
list_activityreads it back. Registering sends no email, and no price, paid mark, payment record or refund changes; a withdrawal closes the team's unpaid payment links. When a replaced player's team has payment marks, the answer says «revisa los pagos de este equipo en el panel».
The «Gestionar torneos» permission
Setting tournaments up needs «Gestionar torneos» (manage), the same way
scheduling needs «Programar partidos»: leave it ticked on SETTO's consent screen
when you sign in, or tick it under Permisos when you create a token; an
organization token with it works only while its creator is still an ADMIN.
Without it every setup write answers 403 INSUFFICIENT_SCOPE, while the search
and the withdrawal preview, which write nothing, keep working.
Draws and results with an assistant
Ask the way you would ask a colleague — "4a varonil plays a group stage and then a knockout, best of three sets", "make two groups", "move Los Tigres to group B", "the first two of each group go through", "confirm the draw", "6-3 6-4 for Pérez / López against Ruiz / Gómez" — and the assistant runs the same steps as the dashboard's «Formato», «Configurar grupos», «Configurar eliminatorias» and «Confirmar cuadro», then records the results. It works on the padel, tennis and pickleball categories of a regular tournament; qualifiers («Clasificatoria»), setting up consolation games, leagues and fútbol stay in the dashboard, while a result and a game's teams go in on any knockout game, third place and consolation included.
- The format (
preview_division_format, thenapply_division_format): a group stage («Fase de Grupos»), a knockout («Eliminatorias») or both, with 1, 2 or 5 sets. Rounds that keep their type keep their games and results, and a round that holds a result is never replaced. A category already playing its groups gets its knockout withappend_elimination_round, which keeps every group game. - The groups (
preview_pools, thenapply_pools): the category's accepted teams split into groups, the seeds («cabezas de serie») apart and the rest by lot, with every game. "Move Los Tigres to group B" is a new preview with the same lot: Los Tigres swap places with a team of group B, and everyone else stays where they were. - The knockout draw (
preview_draw, thenapply_draw): after a group stage, places such as «1ro Pool A» or «2do de 1ros», filled by «Clasificación entre grupos» or «Clasificación de grupos»; in a straight knockout, the teams themselves, seeds first. Byes go to the best places, and the third-place game is optional. A draw takes up to 256 teams. - «Confirmar cuadro» (
confirm_draw), once every group game has its result: each place takes the team the final standings name. - Results (
record_game_result): the assistant reads the game first, so the sets go in its home and away order, then tells you what changed: the standings, or who moved on in the knockout.
The write contract for draws and results
- You see every plan before it is written. A format, groups or a draw is previewed first and nothing is saved: the assistant shows you each group with its teams, the draw's first round and everything it would replace, and waits for your yes. The apply carries the preview's confirmation, valid 15 minutes, and writes exactly that plan; if the category changed in between, nothing is written and the assistant previews again.
- Played games are never rebuilt. A format, groups or a draw that would replace games with results is refused, and a knockout with results is never drawn or seated again.
- A withdrawn team is never seated. When the final standings put a withdrawn team («Baja») in the knockout, the assistant asks you who takes its place: another team of the category, or a BYE that sends its opponent straight through.
- A stored result changes only on your word. When a game already has a result, the assistant shows it to you and asks before replacing it, and clearing a result («Borrar resultado») waits for your yes too. A withdrawn team's W.O.s stay, and a result a player submitted is approved or rejected in the dashboard.
- Warnings come back in Spanish: a set count unusual for the round's format, a group result changed after the knockout was confirmed, or a tournament whose standings count no points yet.
The «Cargar resultados» permission
Recording and clearing results needs «Cargar resultados» (results):
leave it ticked on SETTO's consent screen when you sign in, or tick it under
Permisos when you create a token; an organization token with it works only
while its creator is still an ADMIN. The format, the groups, the draw, its
confirmation and a game's teams need «Gestionar torneos», and their previews,
which write nothing, only «Leer». Without the permission a write answers
403 INSUFFICIENT_SCOPE, and the assistant tells you which one is missing.
How each client connects
| Client | Sign in with your SETTO account | API token |
|---|---|---|
| claude.ai | Yes — the only way | No |
| ChatGPT | Yes — the only way, on the plans OpenAI allows | No |
| Codex | Yes | Yes, from an environment variable |
| Claude Code | Yes | Yes, or the plugin |
| Claude Desktop | Yes, through your claude.ai connectors | Yes, through mcp-remote |
| VS Code | Yes | Yes |
| Cursor | Not yet | Yes — the only way |
Cursor finishes a sign-in by returning to a cursor:// address, and SETTO's
sign-in only returns to https:// and local (http://localhost) addresses, so
Cursor uses a token for now. Where neither way fits, two fallbacks work in every
client:
- The Agent Skill —
setto-apiteaches any agent the same endpoints and it makes plain HTTP calls. - The REST API directly — see the quickstart.
Security notes
- No credential reaches the model. Signing in hands the access token to the app, never to the conversation, and a token belongs in the client's configuration. Never paste a token into a conversation — a pasted token ends up in the transcript and, depending on your setup, in logs.
- Use the environment or the client's secret prompt.
$SETTO_API_TOKENin Claude Code,--bearer-token-env-varin Codex,${env:…}in Cursor, aninputsprompt in VS Code. Do not commit an MCP config with a literal token in it. Claude Desktop's config is the exception that holds one: keep that file private, or use the custom connector. - Writes sit behind a permission and your confirmation. The schedule write
(
apply_schedule_placements) only sets game times, courts and lengths, cannot move a played game and refuses a schedule with a clash; it needs «Programar partidos». The setup writes (tournaments, categories, seeds, teams, players, «Sustitución», «Baja») and the draws (formats, groups, knockout draws, a game's teams) need «Gestionar torneos», and recording or clearing a result needs «Cargar resultados». None of them sends an email, and through them no price, paid mark, payment record or refund changes (a withdrawal closes the team's unpaid payment links). The destructive ones are annotated so, and most MCP clients ask for confirmation before running them, unless you have approved them to always run; a withdrawal, a format, groups and a draw also need the confirmation their preview hands out. Without those three permissions, a confused or prompt-injected model cannot change anything. - You can see and stop everything. Every change an app or a token makes is
recorded in «Actividad», and an assistant can read it back with
list_activity("what did you change yesterday?"). Desconectar in Configuración → Conexiones cuts a signed-in app off at once; revoking a token in Tokens de API does the same for that token. - Scope what you can. Signing in, or a personal token, reaches every tournament you manage; an organization token reaches one organization and nothing else. Grant only the permissions you need. For anything shared — an assistant several people use, or one you do not fully control — prefer an organization token or a read-only one, and create a dedicated token so you can revoke it alone.
- It counts against your rate limit. Tool calls are API requests: 120 per 60 seconds per token, shared with anything else using that token. See Rate limits.
Sample conversations
You: Which categories in Torneo Apertura 2026 still have unfinished games?
Assistant: calls
list_tournamentswithstatus: "IN_PROGRESS"— foundTorneo Apertura 2026(3c9b7f52-…).calls
list_divisionswith that tournament andpopulate: "rounds"— three categories, five rounds between them.calls
get_roundfor each round withpopulate: "games"—Cuarta Fuerza Varonil has 4 of 12 games still
UPCOMING; Primera Fuerza Femenil is complete; Mixta B has 1 game left, scheduled for Saturday 10:00.
You: Schedule Saturday's group games for Cuarta Fuerza and Mixta B on courts 1 and 2, from 9:00, one group per court.
Assistant: calls
get_schedule, thenpropose_pool_per_court_schedulewithday: "2026-11-07",start: "09:00"and the two court idxs —Court 1: Cuarta Fuerza group A, 6 games, 9:00–15:00. Court 2: Mixta B group A, 9:00–12:00, then group B, 12:00–15:00. Every game fits. One miss: Pérez / Gómez prefer to play after 11:00 and their first game is at 10:00. Apply it?
You: Yes.
Assistant: calls
apply_schedule_placementswith those 12 placements — done, 12 games scheduled.
You: Pérez / Soto withdraw from 4a varonil.
Assistant: calls
search_tournamentwithq: "pérez soto", thenpreview_team_withdrawal—They played 2 games (results stay). Game 7 against Ruiz / Gómez: a W.O. for Ruiz / Gómez. Game 12, a quarter-final whose rival is still to be decided: it becomes a bye, and whoever arrives goes straight through. Withdraw them?
You: Yes.
Assistant: calls
withdraw_teamwith the preview's confirmation — done: one W.O. recorded, one bye set, the registration cancelled.
You: Make two groups in 4a varonil.
Assistant: calls
search_tournamentwithq: "4a varonil", thenlist_divisionswithpopulate: ["rounds"], thenpreview_poolswithnumberOfPools: 2—Grupo A: Pérez / López, Ruiz / Gómez, Soto / Díaz, Mora / Vega. Grupo B: Luna / Ríos, Cruz / Peña, Lara / Gil, Paz / Ortiz. 12 games, everyone once in their group; nothing is replaced. Apply it?
You: Move Cruz / Peña to group A first.
Assistant: calls
preview_poolsagain with that pin and the samerngSeed— Grupo A: Pérez / López, Ruiz / Gómez, Cruz / Peña, Mora / Vega. Grupo B: Luna / Ríos, Soto / Díaz, Lara / Gil, Paz / Ortiz. Apply it?You: Yes.
Assistant: calls
apply_poolswith the preview's confirmation — done: two groups, 12 games.You: 6-3 6-4 for Pérez / López against Ruiz / Gómez.
Assistant: calls
get_roundto find the game and its home and away teams, thenrecord_game_resultwith the sets in that order — recorded: Pérez / López win in two sets and lead Grupo A.
If a number looks wrong, ask the assistant which tool call produced it and check that endpoint by hand.
Related
- Sign in with your SETTO account — the OAuth flow, the six permissions, «Conexiones» and «Actividad».
- Agent Skills — the client-agnostic fallback, and what to install when MCP is not an option.
- Docs for LLMs —
llms.txt, per-page Markdown,/openapi.json. - Rate limits — the budget your tool calls share.