Sport Alliance MCP
Run your Magicline or PerfectGym Next studio with natural language. Ask questions or give instructions like "Book Jonas Weber into tonight's Spin class", "Pause Anna Schmidt's contract for August", or "When can Anna cancel her contract at the latest?" — and get instant answers without opening dashboards or writing code.
One install serves every Sport Alliance platform: setup asks which platform your studio is on — Magicline or PerfectGym Next — and configures the rest. Multi-brand operators can connect a Magicline studio and a PerfectGym Next club side by side in the same assistant, each with its own API key and its own permissions.
Built on the Sport Alliance Open API (Magicline docs · PerfectGym Next docs), with optional SQL analytics over the enterprise data warehouse (Magicline · PerfectGym Next, Amazon Redshift).
Not for legacy PerfectGym. This package connects to PerfectGym Next, Sport Alliance's current Open API platform. The classic PerfectGym product (
perfectgym.pl, "Perfect Gym Manager") uses a different API with different authentication and is not supported here.
Supported AI clients:
- Claude Desktop
- Claude Code
- Cursor
- Windsurf
- Gemini CLI
- Antigravity by Google
- any other MCP-compatible client (manual config below)
What is MCP?
Model Context Protocol (MCP) is an open standard that lets AI assistants securely connect to external tools and APIs. This server acts as a bridge between your AI client and your studio platform, translating natural language requests into safe, scoped API calls. There is no server to run or keep alive — your AI client starts it on demand and shuts it down when finished.
Installation
Prerequisites:
-
uv (installs its own Python — nothing else needed):
# macOS / Linux curl -LsSf https://astral.sh/uv/install.sh | sh # Windows (PowerShell) powershell -ExecutionPolicy ByPass -c "irm https://astral.sh/uv/install.ps1 | iex"
-
An Open API key (tenant name + key are in your integration activation email — the base URL looks like
https://<tenant>.open-api.magicline.comfor Magicline studios orhttps://<tenant>.open-api.perfectgym.comfor PerfectGym Next)
Then run the setup wizard:
uvx sportalliance-mcp setup
The first question is your platform — Magicline or PerfectGym Next (with a
built-in "help me tell them apart" if you're unsure: check the hostname in
your activation email). Everything after that is painted in your platform's
colours. Setup asks whether the studio is production or sandbox, shows the
fully resolved API host right in the key prompt so a key can't land on the
wrong platform unnoticed, validates the credentials against the live API and
shows the studio name the key actually opens (it is stored and re-checked
every time the server starts), stores the key in your OS secret store (macOS
Keychain / Windows Credential Manager / Secret Service — never in a
plain-text config file), then lets you pick which AI clients to configure
from an interactive checklist — detected clients are pre-selected, and Claude
Code is configured via claude mcp add --scope user automatically. Restart
your AI client and you're done. Run setup again any time to configure your
other platform alongside the first.
To always use the latest version (auto-update on each client restart), add --auto-update:
uvx sportalliance-mcp setup --auto-update
To skip the platform question (e.g. scripted installs):
uvx sportalliance-mcp setup --platform perfectgym-next
By default, setup configures the server in a safe, read-only mode (no
member data, no writes). To selectively enable elevated capabilities during
setup, pass --advanced:
uvx sportalliance-mcp setup --advanced
What you'll choose (optional):
- Member data / PII (
piitier): access member profiles (including lookup by card/barcode/QR), contracts, check-in history, account balances, payment details, transactions, and membership switch/add previews. - Writes (
writetier): book and cancel classes and appointments, check members in and out, create customers and leads, assign memberships (zero-due offers), cancel contracts, manage idle periods (contract freezes), and log communications. - Individual tools (optional): after picking tiers, setup offers the same
per-category tool editor as
sportalliance-mcp permissions— e.g. keep class bookings but disablecancel_membershipentirely. Existing per-tool disables survive a re-run of setup either way.
IMPORTANT: Enabling writes allows the AI agent to take real, potentially irreversible actions in your studio — including cancelling real member contracts and creating real bookings. Enabling member data exposes personal data of real members, with everything that implies under data-protection law (GDPR, CCPA, and their local equivalents). If you are not in a position to review each tool call before approving it, keep these disabled — especially against a production studio. If you enable them, it is your responsibility to review every action before allowing the agent to proceed.
You can change permissions at any time without re-running setup:
uvx sportalliance-mcp permissions
When both platforms are configured, permissions asks which one you mean
(or pass --platform). Besides switching tiers, this opens a per-category
tool editor: pick a category (memberships, appointments, classes, ...), then
check or uncheck individual tools. Disabled tools are never registered with
the AI client — the agent doesn't see them at all. Selections are stored as a
deny-list (SPORTALLIANCE_TOOLS_EXCLUDE), so tools added in future versions
are enabled by default.
Skipping permission prompts (Claude Code)
Independently of the tiers above, Claude Code asks for approval before every tool call ("Claude wants to use List customers…"). When setup configures Claude Code, it offers to pre-approve tools so those prompts disappear:
- Non-personal reads (recommended): schedules, offers and studio info run without prompting; anything touching member data, and every write action (bookings, cancelations, check-ins), still asks first.
- Everything except destructive actions: no prompts for reads and routine writes; contract signups/cancellations (including withdrawing a cancellation) and financial exports always ask — they are never pre-approved, by design.
- No: keep Claude's default ask-every-time behavior.
To skip the question and pre-approve everything (e.g. scripted installs):
uvx sportalliance-mcp setup --allow-all
This works by merging mcp__Magicline… / mcp__PerfectGymNext… rules into
the permissions.allow list in ~/.claude/settings.json, which both the
Claude Code CLI and its desktop app read. Your existing rules are preserved
(the file is backed up before every rewrite); remove the entries from that
file to get the prompts back. Rules are per platform — pre-approving your
Magicline studio changes nothing for your PerfectGym Next club.
Claude Desktop has no pre-approval config file — use the "Always allow" option in its permission dialog, once per tool. Other clients (Cursor, Windsurf, Gemini CLI) have their own auto-approval settings in their UIs.
What you can do
Run uvx sportalliance-mcp tools to see every tool, grouped by
permission tier. Tools are hand-curated over the Open API with
pagination, rate limiting and retries handled internally, and are identical
on both platforms — the two share one API surface. The warehouse tools
only appear when the optional data warehouse
connection is configured.
Try these prompts — a day at the front desk:
- "Book Jonas Weber into tonight's Spin class"
- "Check Anna Schmidt in"
- "When can Anna cancel her contract at the latest?"
- "What payment method does she have on file, and what's her balance?"
- "Pause her contract for August — vacation"
- "Extend that freeze by a month — what would it cost?"
- "Create a lead for Max Mustermann, max@example.com, and book him a free trial session for tomorrow morning"
- "Assign the 12 Month Fixed membership to customer 10023 from next month"
- "Log that phone call on their record"
…and for the back office:
- "What classes are running tomorrow, and which still have free spots?"
- "How busy is the gym right now?"
- "What membership offers do we sell, and what would Premium cost customer 10023?"
- "Show the account balance and upcoming charges for customer 10023"
Every booking, contract and validate/preview result carries a studio field
naming the platform, tenant and environment it executed against — with
PRODUCTION spelled out — so the assistant (and you, reading the
transcript) always know which studio a write went to.
Data warehouse (optional)
Operators with access to the enterprise data warehouse (Magicline · PerfectGym Next, Amazon Redshift) can enable extra SQL analytics tools. The setup wizard asks about this ("Configure a Redshift data warehouse connection?") — skip it and nothing changes: the warehouse tools are only registered when a connection is configured.
| Tool | Tier | What it does |
|---|---|---|
warehouse_docs |
read | Topic lookup in the built-in glossary (business terms, join keys, KPI definitions, SQL rules) |
warehouse_list_schemas |
read | List queryable schemas |
warehouse_list_tables |
read | List tables/views in a schema (stale __old copies flagged deprecated) |
warehouse_describe_table |
read | Column names, types, nullability |
warehouse_query |
read | Read-only SQL with PII values masked |
warehouse_query_pii |
pii | Read-only SQL, unmasked rows |
Queries run with guardrails: results are capped at 500 rows (with a
truncated flag), a 60-second statement timeout is set, multi-statement
SQL is rejected, and driver errors come back cleaned up with corrective
hints for common Redshift-dialect mistakes.
At read tier, warehouse_query masks values in string/varchar columns and
known personal-data columns such as date_of_birth as "<withheld>" —
row counts and structure stay intact, and enum-like status/type columns
plus period aliases (AS month, AS year, …) stay visible. This masking
is best-effort hygiene, not a security boundary — it keys on result
column names, so aliased queries can slip past it. If you must guarantee
no PII at read tier, disable warehouse_query (via
sportalliance-mcp permissions) or enforce masking in the warehouse itself.
IMPORTANT: connect with a warehouse user that has read-only grants. The server opens read-only transactions and rolls every query back, but arbitrary SQL could escape that — the database user's permissions are the real enforcement.
The password lives in the OS keyring (manage it with
sportalliance-mcp warehouse set|status|delete); host, port, database and
user go into the client config's env block as WAREHOUSE_* variables (see
Environment variables). A group sharing one
warehouse across both platforms stores the password once.
When a warehouse is configured, the server also teaches the AI how to query
it: the key-tables cheat sheet is embedded in the server instructions, and
the full business glossary (definitions, join keys, correct status filters
for every erp_v2 table) is available on demand — by topic through the
warehouse_docs tool, or wholesale as MCP resources
(magicline://warehouse/glossary or
perfectgym-next://warehouse/glossary, per platform).
API Key Management
Key storage: actual key values live in your OS secret store (macOS
Keychain, Windows Credential Manager / DPAPI, Secret Service on Linux),
keyed by platform:tenant — the same tenant name can exist on both
platforms without collision. Only tenant names are kept in
~/.sportalliance-mcp/registry.json, along with each entry's environment
and the verified studio name. On headless Linux without a keyring, fall back
to the SPORTALLIANCE_API_KEY environment variable.
How key selection works: keys are stored per studio. The active tenant
for each platform is whatever SPORTALLIANCE_TENANT is written in that
platform's entry in your client configs — keys activate rewrites it
everywhere in one command, touching only that platform's entries.
# List stored keys grouped by platform (masked), with the active tenant
uvx sportalliance-mcp keys list
# Add a key for another studio (validated against the live API)
uvx sportalliance-mcp keys add
# Switch a platform's configured clients to another studio
uvx sportalliance-mcp keys activate perfectgym-next/tribegym-us
uvx sportalliance-mcp keys activate acme # unambiguous tenants work bare
# Delete a stored key (warns if it's the active one)
uvx sportalliance-mcp keys delete magicline/acme
Open API keys are per studio: multi-studio operators store one key per
tenant and switch with keys activate. Each key remembers its environment
(production, sandbox, or a custom URL — chosen when it was added), and
keys activate switches the endpoint together with the tenant.
Checking your setup
uvx sportalliance-mcp status
status is a local doctor — no network, safe to run blind. It checks every
configured client entry for the disagreements that actually break things:
entry key vs declared platform, platform vs base-URL host, environment vs
host, the same inline API key pasted under two different platforms, stale
MAGICLINE_*/SPORTALLIANCE_* twins that disagree, launcher paths that no
longer exist, missing keyring entries, and Claude Code allow rules that match
no configured entry.
uvx sportalliance-mcp test goes one step further and verifies every
configured entry against the live API, printing the studio name each key
actually opens.
Upgrading from magicline-mcp
Run uvx sportalliance-mcp setup — it detects an existing magicline-mcp
installation and offers to migrate before anything else. Migration copies
every discoverable key into the new keyring service (verified by read-back,
deleting nothing), writes the new registry (leaving the old one in
place), backs up each client config, and rewrites the existing Magicline
entry with both env prefixes — so the config keeps working under a cached
old binary, under the new package, and can simply be restored from the
backup if you ever want to roll back. The MCP server key stays exactly
Magicline: existing Claude Code allow rules keep working untouched, and
your AI client shows the same server name as before.
Staying on magicline-mcp 0.1.2 is also fine — it keeps working and nothing
breaks. Configs carried over by hand (just the MAGICLINE_* env block) work
with zero action: the server recognises the legacy prefix and serves the
Magicline platform, printing a one-line deprecation note.
Claude Code
setup --claude-code configures Claude Code automatically by running
claude mcp add --scope user for you (user scope, so the server is
available in every directory, not just the one setup ran in), and then
offers to pre-approve tools (see
Skipping permission prompts).
Or do it manually:
claude mcp add PerfectGymNext --scope user \
-e SPORTALLIANCE_PLATFORM=perfectgym-next \
-e SPORTALLIANCE_TENANT=<tenant> \
-e SPORTALLIANCE_ENVIRONMENT=production \
-e SPORTALLIANCE_TOOLS=read -- uvx sportalliance-mcp
# Verify it was added
claude mcp list
Manual configuration
The setup wizard edits these files for you, but you can also edit them by hand:
- Claude Desktop:
~/Library/Application Support/Claude/claude_desktop_config.json(Windows:%APPDATA%\Claude\claude_desktop_config.json) - Cursor:
~/.cursor/mcp.json - Windsurf:
~/.codeium/windsurf/mcp_config.json - Gemini CLI:
~/.gemini/settings.json - Antigravity:
~/.gemini/antigravity/mcp_config.json
All use the same format (for Gemini CLI, the mcpServers block lives inside
its existing settings.json — the wizard merges without touching your other
settings). Two platforms from one install look like this (keys come from the
OS keyring, stored by setup or keys add):
{
"mcpServers": {
"Magicline": {
"command": "uvx",
"args": ["sportalliance-mcp"],
"env": {
"SPORTALLIANCE_PLATFORM": "magicline",
"SPORTALLIANCE_TENANT": "acme-fitness",
"SPORTALLIANCE_ENVIRONMENT": "production",
"SPORTALLIANCE_TOOLS": "read"
}
},
"PerfectGymNext": {
"command": "uvx",
"args": ["sportalliance-mcp"],
"env": {
"SPORTALLIANCE_PLATFORM": "perfectgym-next",
"SPORTALLIANCE_TENANT": "tribegym-us",
"SPORTALLIANCE_ENVIRONMENT": "sandbox",
"SPORTALLIANCE_TOOLS": "read"
}
}
}
}
Alternative — environment variable instead of the keyring (CI, Docker,
headless Linux): add "SPORTALLIANCE_API_KEY": "your-api-key-here" to the
env block. Never paste the same key into two different platforms' entries —
keys are per studio, and status flags exactly that mistake.
On Windows, prefer the full path to
uvx.exeascommand— GUI apps don't always inherit your shell's PATH. The setup wizard does this automatically.
CLI reference
| Command | What it does |
|---|---|
sportalliance-mcp setup |
One-time interactive setup (platform question first; safe read-only mode) |
sportalliance-mcp setup --platform <id> |
Skip the platform question (magicline, perfectgym-next) |
sportalliance-mcp setup --advanced |
Setup with elevated capabilities (member data, writes, per-tool fine-tuning) |
sportalliance-mcp setup --auto-update |
Clients always launch the latest published version |
sportalliance-mcp setup --claude-code |
Also configures Claude Code via claude mcp add --scope user |
sportalliance-mcp setup --allow-all |
Pre-approve tools in Claude Code — writes included, but destructive contract/payment actions still ask |
sportalliance-mcp test |
Verify every configured entry against the live API |
sportalliance-mcp status |
Local config doctor — spot misconfigurations without any network |
sportalliance-mcp tools |
List every tool, grouped by permission tier |
sportalliance-mcp permissions [--platform p] |
Change tiers or enable/disable individual tools |
sportalliance-mcp keys list |
Show stored keys grouped by platform (masked), environments, active tenants |
sportalliance-mcp keys add |
Store a key for another studio |
sportalliance-mcp keys activate <p/tenant> |
Switch a platform's clients to another studio (and its environment) |
sportalliance-mcp keys delete <p/tenant> |
Remove a stored key |
sportalliance-mcp warehouse set|status|delete |
Manage the data-warehouse password in the OS keyring |
sportalliance-mcp |
Run the MCP server on stdio — your AI client does this for you |
(Prefix with uvx, or uv run inside the repo.)
Environment variables
Variables marked managed are written by the setup wizard; you only set them
yourself in non-interactive environments. MAGICLINE_* equivalents of the
serve-time variables remain supported for existing Magicline configs
(deprecated; if both prefixes are set they must agree).
| Variable | Managed | Description |
|---|---|---|
SPORTALLIANCE_PLATFORM |
✅ | Which platform this entry serves: magicline or perfectgym-next (aliases perfectgym, pgnext). Required — the server refuses to guess. |
SPORTALLIANCE_TENANT |
✅ | Your tenant/studio name (the <tenant> in the base URL). Required. |
SPORTALLIANCE_ENVIRONMENT |
✅ | production (default) or sandbox. Explicit — never inferred from other settings. |
SPORTALLIANCE_TOOLS |
✅ | Enabled tiers, comma-separated: read (default), pii, write. read is always included. |
SPORTALLIANCE_TOOLS_EXCLUDE |
✅ | Individual tools to disable, comma-separated (e.g. cancel_contract,create_tax_advisor_export). Applied after tier filtering; unknown names are ignored with a warning. Managed by sportalliance-mcp permissions. |
SPORTALLIANCE_API_KEY |
API key. Overrides the OS keyring — for CI, Docker, or headless machines. | |
SPORTALLIANCE_BASE_URL |
✅ | Custom API base URL. Written by the wizard for sandbox/custom environments. HTTPS required (plain http only for localhost). Refused if the host belongs to a different platform than SPORTALLIANCE_PLATFORM. |
SPORTALLIANCE_MAX_RPS |
— | Client-side request ceiling in requests/second (default 3). Keeps the MCP to a small slice of the API key's rate allowance, which your other integrations share. 0 disables the throttle. |
WAREHOUSE_HOST |
✅ | Redshift endpoint of the enterprise data warehouse. Warehouse tools register only when host, database and user are all set. |
WAREHOUSE_PORT |
✅ | Warehouse port (default 5439). |
WAREHOUSE_DATABASE |
✅ | Warehouse database name. |
WAREHOUSE_USER |
✅ | Warehouse user — use one with read-only grants. |
WAREHOUSE_PASSWORD |
Warehouse password. Overrides the OS keyring — only needed where no keyring exists. |
Troubleshooting
- "SPORTALLIANCE_PLATFORM is not set" — add it to the entry's env block
(
magiclineorperfectgym-next), or re-runuvx sportalliance-mcp setup. - "No API key found for tenant" — run
uvx sportalliance-mcp setup, or setSPORTALLIANCE_API_KEY. Verify withuvx sportalliance-mcp test. - "tenant does not exist" (404) — sandbox and production are separate
tenant namespaces: a sandbox studio only resolves on
<tenant>.open-api.sandbox.<platform-domain>. Setup offers the switch with one keystroke. - 401 Unauthorized — tenant and key don't match, or the integration was
deactivated. Both come from the same activation email. Also check the key
isn't from your other platform —
uvx sportalliance-mcp statusflags a key pasted under two platforms. - 403 Permission denied — three possible causes: your API key lacks the scope for that operation, the entity belongs to a different studio, or the member has opted out of third-party data access (their right — the error message says which).
- The server refuses to start with a "STOPPING" identity message — the
API key opens a different studio than the one this entry was configured
for. Re-run setup for that platform, or inspect with
uvx sportalliance-mcp status. - Tools missing in your client — member data and write tools only appear
when their tier is enabled, and individual tools may have been disabled:
check
uvx sportalliance-mcp permissions. Restart the client after any config change. claudeCLI not found (with--claude-code) — install Claude Code first, then re-runuvx sportalliance-mcp setup --claude-code.- "Server disconnected" in Claude Desktop — check the server log at
~/Library/Logs/Claude/mcp-server-Magicline.logormcp-server-PerfectGymNext.log(macOS); the last Python traceback usually names the cause. - Keyring issues on Linux — headless machines often have no Secret
Service; use the
SPORTALLIANCE_API_KEYenv var in the client config instead.
Development
uv sync
uv run sportalliance-mcp tools
uv run pytest
Project layout:
src/sportalliance_mcp/
├── cli.py # entry point + subcommands
├── platforms.py # the platform registry: Magicline, PerfectGym Next, ...
├── config.py # platform/tenant/key/tier resolution (env > keyring)
├── registry.py # ~/.sportalliance-mcp/registry.json, keyed (platform, tenant)
├── client.py # httpx wrapper: auth, retries, backoff, pagination
├── server.py # FastMCP assembly, identity check, studio stamps
├── setup_wizard.py # the one-time setup experience (platform picker first)
├── manage.py # keys + permissions + the `status` doctor
├── migrate.py # copy-forward migration from magicline-mcp
├── warehouse.py # read-only Redshift client (optional warehouse tools)
├── branding.py # terminal UI (per-platform palettes and banners)
└── tools/ # one module per API domain
Note (macOS + iCloud): if this repo lives in an iCloud-synced folder (e.g.
~/Documents), iCloud recursively stamps the macOS hidden flag on dot-directories — and Python ≥ 3.13.4 refuses to load hidden.pthfiles, which silently breaks the venv. Do not work around it with a.venvsymlink — iCloud materializes symlinks into broken directory copies. Instead, keep the venv in a*.nosyncdirectory (iCloud ignores those) by setting, e.g. in~/.zshenv:export UV_PROJECT_ENVIRONMENT=".venv.nosync"The simplest alternative: keep code outside iCloud-synced folders entirely.
License
This project is licensed under the MIT License — see LICENSE.
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 sportalliance_mcp-0.2.0.tar.gz.
File metadata
- Download URL: sportalliance_mcp-0.2.0.tar.gz
- Upload date:
- Size: 195.0 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
007f17aedf479080ccee23e7e2190703b9be82d59142abddcbcd3bff0a415b45
|
|
| MD5 |
a8e3985de0763afb36386f41231febfb
|
|
| BLAKE2b-256 |
7ba61590a8d0a429d3172c8a145261efb16e4df8913fdd899a4fc0add51905fe
|
File details
Details for the file sportalliance_mcp-0.2.0-py3-none-any.whl.
File metadata
- Download URL: sportalliance_mcp-0.2.0-py3-none-any.whl
- Upload date:
- Size: 102.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via:
uv/0.11.29 {"installer":{"name":"uv","version":"0.11.29","subcommand":["publish"]},"python":null,"implementation":{"name":null,"version":null},"distro":{"name":"macOS","version":null,"id":null,"libc":null},"system":{"name":null,"release":null},"cpu":null,"openssl_version":null,"setuptools_version":null,"rustc_version":null,"ci":null}
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
d5258a82cf6b7f20a4a1f2536d03ebe82285de1d2010bfbc2b6cfc1a065dc0b4
|
|
| MD5 |
83bcaf22d96502def32ff980c80c8f0e
|
|
| BLAKE2b-256 |
2f149246ce7b691e86651ff3f92964fc723472426b4ddc491a26ae480ad8f5f4
|