Skip to main content

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:

  1. GET /Homepage.aspx → session cookie + hidden __VIEWSTATE, __VIEWSTATEGENERATOR, __EVENTVALIDATION.
  2. POST /Homepage.aspx echoing those hidden fields plus …UserLogin$UserName, …UserLogin$Password, …UserLogin$LoginSubmitButton.
  3. The <asp:LoginView> widget swaps to its authenticated template; cookies now carry the session.

See cm365/client.py.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

clubmanager365cli-0.1.0.tar.gz (20.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

clubmanager365cli-0.1.0-py3-none-any.whl (22.9 kB view details)

Uploaded Python 3

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

Hashes for clubmanager365cli-0.1.0.tar.gz
Algorithm Hash digest
SHA256 60d2b737de3f33f5c70417b5542fb5e872a9710edf2f9257dddc2faa6f2e5f12
MD5 2e3cd01cbb6a2f2ba5af07d1836490f2
BLAKE2b-256 2466a323af0f42450dd07e896c3965c4b1d04067776c7218440527defd5a6690

See more details on using hashes here.

File details

Details for the file clubmanager365cli-0.1.0-py3-none-any.whl.

File metadata

File hashes

Hashes for clubmanager365cli-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 449185dbd2cd4304613410d81077907e9289756e1b6175aa546871a395a638c6
MD5 1e9ee0728a4d2b2e23627602d78a8e85
BLAKE2b-256 56d5c9381ae0597f1dc37291c08fbb71a74e824a8c024bac1b23bd826a188019

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page