CLI and MCP server to log in and book courts on clubmanager365.com
Project description
clubmanager365cli
A command-line tool to log in to clubmanager365.com and book courts from the terminal — and an MCP server exposing the same actions so AI agents can book courts for you.
Personal automation for your own account. Use responsibly and within your club's terms of use.
Booking rules
Each club configures its own booking rules, so your club may differ. By default this tool assumes the same rules as the club it was developed against:
- Every booking requires at least one opponent (
book --with <name|id>). - One slot per person per day — booking a day you already have fails.
- Booking needs no payment at the time of booking (covered by membership / court credits), so there's no checkout step.
Setup
python3 -m venv .venv
source .venv/bin/activate
pip install -e .
Then provide your credentials (kept local, git-ignored):
cp credentials.env.example credentials.env
Then open credentials.env in an editor and fill in your username and password.
Alternatively, export them as environment variables (quote both values — usernames and passwords can contain spaces):
export CM365_USERNAME="your username"
export CM365_PASSWORD="your password"
If your club's match type differs from the default (4 = Friendly), set
CM365_MATCH_TYPE too — run cm365 match-types to find your club's ids. This
applies to both the CLI and the MCP server.
Usage
cm365 login # verify your credentials work
cm365 mybookings # list your upcoming bookings
cm365 slots tomorrow -a # free slots tomorrow
cm365 slots 2026-07-04 -t 18:00 # all courts at 18:00 on a date
cm365 slots today --type indoor # restrict to indoor courts
cm365 players "pat smith" # find an opponent's id by name (quote names with spaces)
cm365 match-types # list your club's match-type ids (e.g. Friendly)
# Booking requires an opponent and is a dry run unless you pass --yes:
cm365 book tomorrow 18:00 --with "Pat Smith" # dry run (finds slot)
cm365 book tomorrow 18:00 -c "Indoor Court 1" --with "Pat Smith" --yes
cm365 book tomorrow 18:00 --with 100001 --with 100002 --yes # doubles, by id
cm365 cancel 12345678 --yes # cancel a booking by id (from mybookings)
Dates accept today, tomorrow, YYYY-MM-DD, or 27 Jun 2026.
Times accept 18, 18:00, or 6pm. Opponents accept names (fuzzy) or ids.
Diagnostics
cm365 whoami # post-login landing page + nav links
cm365 explore [PATH] -o page.local.html # dump a page's HTML/forms/links
MCP server
The same actions are exposed as an MCP server so an AI assistant (Claude Desktop, Claude Code, …) can book courts for you. It runs locally over stdio with your own credentials — there is no shared/hosted server, so your login never leaves your machine.
Tools: list_slots, my_bookings, search_players, list_match_types,
book_court, cancel_booking. book_court and cancel_booking are a dry
run unless you pass confirm: true, so the assistant can't book or cancel
without an explicit confirmation step.
Run it
No manual install needed — uv runs it (and
provisions a suitable Python; the MCP SDK needs 3.10+):
# from PyPI (once published):
uvx --from "clubmanager365cli[mcp]" clubmanager365-mcp
# or straight from a clone / GitHub:
uvx --from "git+https://github.com/jerry-shao/clubmanager365cli#egg=clubmanager365cli[mcp]" clubmanager365-mcp
Connect a client
Claude Desktop — add to claude_desktop_config.json:
{
"mcpServers": {
"clubmanager365": {
"command": "uvx",
"args": ["--from", "clubmanager365cli[mcp]", "clubmanager365-mcp"],
"env": {
"CM365_USERNAME": "your-username",
"CM365_PASSWORD": "your-password"
}
}
}
}
Claude Code:
claude mcp add clubmanager365 \
--env CM365_USERNAME=your-username \
--env CM365_PASSWORD=your-password \
-- uvx --from "clubmanager365cli[mcp]" clubmanager365-mcp
Kiro CLI — add to ~/.kiro/settings/mcp.json (global) or
.kiro/settings/mcp.json (per workspace):
{
"mcpServers": {
"clubmanager365": {
"command": "uvx",
"args": ["--from", "clubmanager365cli[mcp]", "clubmanager365-mcp"],
"env": {
"CM365_USERNAME": "your-username",
"CM365_PASSWORD": "your-password"
}
}
}
}
Codex CLI — add to ~/.codex/config.toml:
[mcp_servers.clubmanager365]
command = "uvx"
args = ["--from", "clubmanager365cli[mcp]", "clubmanager365-mcp"]
env = { CM365_USERNAME = "your-username", CM365_PASSWORD = "your-password" }
The booking API
All booking actions go through /Club/ActionHandler.ashx, with the request
object serialised as a JSON string carried on the request, matching the calls
the site's own front-end makes:
/Club/ActionHandler.ashx?siteCallback=CourtCallback&action=GetCourtDay&_=<ts>&{"Date":"27 Jun 2026",...}
When a booking takes no payment at booking time (e.g. it's covered by
membership or court credits), booking is a single MakeBooking call — no
preliminary hold and no BookingPlayerID are needed. GetCourtDay lists the
slots (each cell carries a CourtSlotID; each column a CourtID), and
MakeBooking takes CourtsRequired: [{c: CourtID, s: CourtSlotID}] plus
OpponentPlayerIDs, SelectedMatchType, MatchDate, etc. Clubs that take
payment instead go through SaveNewPreliminaryBooking (a short-lived hold)
before confirming — that path isn't exercised here.
See cm365/bookings.py.
How login works
The site is ASP.NET WebForms. Logging in is a "postback" on the homepage:
GET /Homepage.aspx→ session cookie + hidden__VIEWSTATE,__VIEWSTATEGENERATOR,__EVENTVALIDATION.POST /Homepage.aspxechoing those hidden fields plus…UserLogin$UserName,…UserLogin$Password,…UserLogin$LoginSubmitButton.- The
<asp:LoginView>widget swaps to its authenticated template; cookies now carry the session.
See cm365/client.py.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file clubmanager365cli-0.1.0.tar.gz.
File metadata
- Download URL: clubmanager365cli-0.1.0.tar.gz
- Upload date:
- Size: 20.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
60d2b737de3f33f5c70417b5542fb5e872a9710edf2f9257dddc2faa6f2e5f12
|
|
| MD5 |
2e3cd01cbb6a2f2ba5af07d1836490f2
|
|
| BLAKE2b-256 |
2466a323af0f42450dd07e896c3965c4b1d04067776c7218440527defd5a6690
|
File details
Details for the file clubmanager365cli-0.1.0-py3-none-any.whl.
File metadata
- Download URL: clubmanager365cli-0.1.0-py3-none-any.whl
- Upload date:
- Size: 22.9 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: uv/0.7.16
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
449185dbd2cd4304613410d81077907e9289756e1b6175aa546871a395a638c6
|
|
| MD5 |
1e9ee0728a4d2b2e23627602d78a8e85
|
|
| BLAKE2b-256 |
56d5c9381ae0597f1dc37291c08fbb71a74e824a8c024bac1b23bd826a188019
|