Magicline Studio MCP

Run your studio with natural language.

$ uvx magicline-mcp setup
███╗   ███╗ █████╗  ██████╗ ██╗ ██████╗██╗     ██╗███╗   ██╗███████╗
████╗ ████║██╔══██╗██╔════╝ ██║██╔════╝██║     ██║████╗  ██║██╔════╝
██╔████╔██║███████║██║  ███╗██║██║     ██║     ██║██╔██╗ ██║█████╗
██║╚██╔╝██║██╔══██║██║   ██║██║██║     ██║     ██║██║╚██╗██║██╔══╝
██║ ╚═╝ ██║██║  ██║╚██████╔╝██║╚██████╗███████╗██║██║ ╚████║███████╗
╚═╝     ╚═╝╚═╝  ╚═╝ ╚═════╝ ╚═╝ ╚═════╝╚══════╝╚═╝╚═╝  ╚═══╝╚══════╝
Magicline Studio MCP v0.1.1
Tools for the Magicline Open API in Claude, Cursor, etc. Read-only by default — member data and writes are opt-in.
Documentation: developer.sportalliance.com/apis/magicline
$
Works with
Claude DesktopClaude CodeCursorWindsurfGemini CLIAntigravity

One standard between your AI
assistant and Magicline.

Model Context Protocol lets AI assistants securely connect to external tools. This server sits in the middle, translating plain language into safe, scoped calls to the Magicline Open API. There's nothing to run or keep alive: your client starts it on demand and shuts it down when finished.

94 hand-curated tools covering classes, bookings, members and contracts, plus SQL analytics over the Magicline data warehouse, every one gated behind permission tiers you control.

Up and running in minutes.

An interactive wizard validates your credentials against the live API, stores your key securely, and configures every AI client you pick.

1

Install uv

It brings its own Python, nothing else to install. One line for macOS, Linux or Windows.

2

Run the wizard

Run uvx magicline-mcp setup, no clone, no install step, uv fetches the package from PyPI. It asks whether your studio is production or sandbox, validates your credentials live, stores the key in your OS secret store, then lets you pick clients from a checklist, detected ones are pre-selected.

3

Restart your AI client

Magicline appears in the client's tools list. In Claude Desktop: Settings → Developer. In Cursor: Settings → Tools.

4

Ask something

“What classes are running tomorrow?” If it answers, you're done.

install from PyPI
# install uv (macOS / Linux)
curl -LsSf https://astral.sh/uv/install.sh | sh

# run the setup wizard
uvx magicline-mcp setup

# enable member data + writes
uvx magicline-mcp setup --advanced

# always launch the latest release
uvx magicline-mcp setup --auto-update
you'll need
  • uv, the installer that carries its own Python runtime. Nothing else to install.
  • A Magicline Open API key, tenant name and key arrive in your integration activation email.
  • A desktop MCP client, websites can't reach a local server, so use a desktop app or CLI.

Test in a sandbox firstThe setup wizard asks whether your studio is production or sandbox and configures the endpoint for you, choose sandbox before you enable writes against anything real.

Three tiers. You decide
what the assistant can touch.

Tiers control which tools exist at all: the server never even registers write tools without the write tier. Change them anytime with magicline-mcp permissions, which also lets you enable or disable individual tools per category (memberships, appointments, classes, ...), so you can allow bookings while keeping cancelations off entirely.

always on
read

Read

The safe default
  • Classes, schedules & free spots
  • Appointment & trial-offer slots
  • Membership offers & pricing previews
  • Studio utilisation & employees
  • All validations & previews
pii

Member data

Personal data (opt-in)
  • Member profiles & contact details
  • Contracts & cancellation terms
  • Check-in history & balances
  • Payment details & transactions
  • Debt-collection data
write

Writes

Real actions (opt-in)
  • Book & cancel classes / appointments
  • Check members in & out
  • Create customers & leads
  • Assign memberships, cancel contracts
  • Freeze contracts, log communications

Enabling writes and member data has real consequencesThe agent can take irreversible actions, including cancelling real member contracts, and member data exposes personal data under GDPR. If you can't review each tool call before approving it, keep these off, especially against production. Pre-approval (Claude Code's --allow-all) controls whether Claude asks; tiers control what exists. They're independent.

Skipping the permission prompts Claude Code

Independently of the tiers, Claude Code asks for approval before every tool call. When setup configures it, it offers to pre-approve Magicline tools so those prompts disappear, a bypass you choose the scope of.

Recommended

Read-only tools

Lookups, schedules, previews and validations run without prompting. Write actions (bookings, cancellations, check-ins) still ask first.

Full bypass

Everything

No prompts at all, writes included. setup --allow-all sets this in one shot, for scripted or headless installs.

Default

No pre-approval

Keep Claude's ask-every-time behaviour: nothing is pre-authorised, and you approve each call as it happens.

Under the hood this merges mcp__Magicline… rules into permissions.allow in ~/.claude/settings.json, which both the CLI and desktop app read. Your existing rules are preserved, remove the Magicline entries there to get the prompts back.

Other clients differClaude Desktop has no pre-approval file. Use its “Always allow” dialog option, once per tool. Cursor, Windsurf and Gemini CLI each have their own auto-approve settings in their own UIs.

A day at the front desk.

Just ask. The assistant figures out which tools to use. As with any AI, if the first phrasing doesn't land, try another.

Front desk members & walk-ins

>How full is the gym right now, and which classes today still have free spots?
>Lenore is at the desk without her card. Find her, confirm her membership is active, and check her in.three calls, no clicks
>A walk-in wants to try a class. Show me what Jonas can trial and book him into the earliest slot.every write validated before it runs
>Lenore wants a body composition analysis this week. Find the earliest free slot and book her in.
>The showers were cold this morning. Log Lenore's call on her record and check whether we may follow up by email.

Contracts & pricing the hard questions

>Lenore wants to pause her membership for 3 weeks from the 1st. What's her free allowance, what would it cost, and set it up.
>When is the earliest Lenore could cancel, what's the notice deadline, and what would she still owe? Don't cancel anything.
>She called back, she's staying. Withdraw the cancelation.
>What memberships do we offer, and exactly what would Erika pay to start Monday? Compare monthly against 12 months upfront.quotes both tariffs, creates nothing
>What did we just do for Lenore today?no tool calls, pure recap from context

Every tool, by tier.

The complete set of 94 tools. Read tools are always available; member-data and write tools only exist once their tier is enabled. Click any tool for its description, or run magicline-mcp tools in your terminal.

Readread25 tools · always on
get_additional_modules

Get the studio's additional modules (paid add-ons like drink flatrate, solarium) available in member self-service.

get_appointment_slots

Get available time slots for a bookable appointment type. Slots are calculated from slot_window_start_date (YYYY-MM-DD, default today) up to days_ahead later (maximum 6 days). An empty result means no free slots in that window, try a later start date.

get_bookable_appointment

Get one bookable appointment type by its ID.

get_class

Get a single class (group fitness course) by its ID.

get_class_slot

Get one specific class slot with its current state (times, instructor, free capacity, booking windows). If class_id is omitted, the slot is located by scanning upcoming slots across all classes.

get_contract_cancelation_reasons

Get the studio's configured contract cancelation reasons (needed to create a cancelation).

get_lead_config

Get the studio's lead configuration: which fields are required or available when creating a lead.

get_membership_offer

Get one membership offer with full details (terms, pricing, modules).

get_studio_information

Get general information about the studio: name, address, contact details, opening hours and configuration.

get_studio_utilization

Get the studio's current utilization (how busy the gym is right now).

get_trial_offer_appointment_slots

Get available slots for a trial-offer appointment type.

get_trial_offer_class_slots

Get bookable trial-offer slots for one class.

get_trial_offer_config

Get a trial offer configuration by its ID.

list_additional_information_fields

List the studio's configured additional information fields, the custom profile fields available on every customer (IDs, names, types and allowed values), e.g. a 'Front desk notes' text field. When asked to add a note or custom info to a customer's PROFILE, check here first for a matching field, then write it with set_additional_information_fields.

list_bookable_appointments

List the studio's bookable appointment types (e.g. personal training, body analysis, consultations).

list_class_slots

List upcoming bookable class slots (scheduled sessions) with start time, instructor and free capacity, across all classes, or for one class via class_id. Optional from_date/to_date (YYYY-MM-DD, inclusive) filter by day. Slots exist only as far ahead as the studio has published its schedule (often ~2 weeks): schedule_published_until in the response is that horizon, dates beyond it aren't bookable *yet*, rather than free or full.

list_classes

List the studio's active classes (group fitness courses) with title, description and schedule information.

list_membership_offers

List all membership offers (tariffs/plans) the studio currently sells.

list_trial_offer_appointments

List appointment types that can be booked as a trial offer.

list_trial_offer_classes

List classes that can be booked as a trial offer.

warehouse_describe_table

Describe the columns of a warehouse table: column_name, data_type, is_nullable, and column_default.

warehouse_docs

Look up data warehouse documentation by topic: business definitions, per-table analyst notes (correct filters, join keys, gotchas) and SQL rules. Call without a topic to list available topics; with a topic it matches section names first, then falls back to keyword search (e.g. "churn", "KPI", "idle", "tables"). Consult this before writing non-trivial SQL.

warehouse_list_schemas

List the queryable schemas in the data warehouse.

warehouse_list_tables

List tables and views in a warehouse schema. Returns table_name and table_type (BASE TABLE or VIEW) for each entry. Entries flagged deprecated: true (names ending __old) are stale copies, ignore them.

warehouse_query

Run a read-only SQL query against the data warehouse. Values in string/varchar columns are masked as "<withheld>" (they may contain PII); row counts and structure stay truthful. Alias derived period labels AS month/year/quarter/week to keep them visible. Use warehouse_query_pii for unmasked results when the pii tier is enabled. Redshift SQL dialect: no FILTER clause (use SUM(CASE WHEN ... END)), no ILIKE ANY; DATE_TRUNC, LISTAGG and window functions are available. Results are capped at 500 rows (truncated: true when the cap hits), prefer aggregates. Numeric/decimal values are returned as JSON strings to preserve precision. Returns {columns, rows, withheldColumns, truncated}.

Member datapii35 tools · opt-in
get_account_transactions

Get a customer's past account transactions (charges with their open amounts). Optional from_date/to_date (YYYY-MM-DD, inclusive) filter by the transaction's dueDate. Note: the API exposes charges only, no settlement records (payment-received dates or payment method per transaction).

get_appointment_booking

Get a single appointment booking by its booking ID.

get_appointment_bookings

Get a customer's appointment bookings within roughly +/- 2 weeks of today.

get_class_booking

Get a single class booking by its booking ID (including the customer).

get_class_bookings

Get all class bookings for a specific customer.

get_communication_preferences

Get a customer's communication preferences (which channels they accept per message category: CONTRACT, GENERAL, APPOINTMENT, NEWSLETTER, LOYALTY_PROGRAM).

get_contract_data

Get a customer's contract data as shown in member self-service, including cancelation options.

get_customer

Get a customer's full profile by their ID. Includes cardNumbers: the member's club access card number(s), ordinary front-desk data that staff can freely see and share with the member (NOT a payment card number).

get_customer_balance

Get a customer's account balance data (credits and open amounts).

get_customer_benefits

Get a customer's (partner integration) benefits, optionally filtered by benefit keys.

get_customer_benefits_by

Get a customer's benefits by a member identifier (access card number, barcode or PIN) instead of their customer ID. Provide exactly one identifier. Optional keys filter checks only those benefits.

get_customer_by

Look up a customer by a member identifier: club access card number, customer number, barcode, QR code UUID, PIN, or debtor ID. Provide exactly one. card_number is the number on the member's access card (not a payment card). card_number_format (for card lookups): DECIMAL, HEX_MSB or HEX_LSB.

get_customer_checkins

Get a customer's studio check-in history. Dates are YYYY-MM-DD; the range must not exceed 365 days.

get_customer_contract

Get one membership contract of a customer by contract ID.

get_customer_contracts

Get a customer's membership contracts. Optional status filter: ACTIVE or INACTIVE.

get_customer_transactions

Get a customer's transactions in a date range (YYYY-MM-DD, max 365 days).

get_debt_claim_preview

Preview the future debt claims (upcoming dues) for one of the customer's contracts, e.g. what they would still owe through the remaining term.

get_employee

Get a single employee by their ID.

get_idle_period

Get one idle period (pause/freeze/hold) by its ID, current state, dates and verification status.

get_idle_period_config

Get the idle period (pause/freeze/hold) configuration of a contract: allowed reasons, durations and limits. Call this before validate_idle_period/create_idle_period, its temporalUnit is the only unit the contract accepts.

get_idle_periods

Get the idle periods (contract pauses/freezes/holds) of a contract.

get_membership_switch_config

Get one membership switch configuration for a customer, including the destination offers, terms and modules available for that switch path.

get_membership_switch_configs

Get the membership switch paths (upgrades/downgrades) available to a customer. An empty list means the customer is not eligible for any switch.

get_payment_details

Get the payment details a customer has on file (payment method / mandate information).

get_purchasable_additional_modules

Get the additional modules (add-ons) a specific contract could purchase.

get_remaining_idle_periods

Get how many idle-period (pause/freeze) free terms and max terms the contract has left.

get_tax_advisor_export

Get a tax advisor export by its ID (status and download information).

get_upcoming_transactions

Get a customer's upcoming account transactions within the next year (future dues and scheduled charges).

list_customers

List customers. Optional customer_status filter: MEMBER, PROSPECT or FORMER_MEMBER.

list_employees

List the studio's employees (trainers and staff).

preview_add_membership

Preview adding a new contract to an existing customer without creating it, the authoritative price calculation including their discounts. dueOnSigningAmount is the mandatory amount payable at signing; the payment schedule may also list same-day charges flagged as non-mandatory (e.g. optional modules), those are NOT part of the amount due at signing. Get term IDs from get_membership_offer. The actual signup requires the studio's payment frontend and is not available as a tool.

preview_membership_signup

Preview a brand-new membership signup (price quote for a prospect) without creating anything. customer follows the Magicline customer schema, at minimum firstName, lastName, dateOfBirth, email, street, city, zipCode, countryCode and language {"languageCode": ...}. dueOnSigningAmount is the authoritative mandatory amount payable at signing; the payment schedule may also list same-day charges flagged as non-mandatory (e.g. optional modules), those are NOT part of the amount due at signing. If dueOnSigningAmount is 0, the signup can be completed with signup_membership; otherwise it must go through the studio's payment frontend.

preview_membership_switch

Preview a membership switch (upgrade/downgrade) without performing it, the authoritative source for pro-rated costs and fees (paymentPreview.dueOnSigningAmount). Performing the actual switch requires the studio's payment frontend and is not available as a tool.

search_customers

Search customers by name (prefix match), email, date of birth (YYYY-MM-DD) or phone number (+49... format). Provide at least one criterion.

warehouse_query_pii

Run a read-only SQL query against the data warehouse with full, unmasked results including all string/varchar columns (PII). Requires the pii tier. Redshift SQL dialect: no FILTER clause (use SUM(CASE WHEN ... END)). Results are capped at 500 rows (truncated: true when the cap hits), prefer aggregates. Numeric/decimal values are returned as JSON strings to preserve precision. Returns {columns, rows, truncated}.

Writeswrite34 tools · opt-in
add_membership

**Destructive, never pre-approved; a human confirms every call.** Assign a membership contract to an existing customer, a REAL, binding contract; confirm details with the user first. Always run preview_add_membership first: this works directly only when the preview's dueOnSigningAmount is 0 (nothing to charge at signing). If it is greater than 0, the signup must go through the studio's payment frontend instead, tell the user rather than attempting it. Get term IDs from get_membership_offer.

add_to_communication_thread

Add a communication entry to an existing thread on a customer's record. Same fields as create_communication_thread; thread_status updates the thread (CREATED, ONGOING or CLOSED). The API cannot list or read existing threads, so thread_id must come from a create_communication_thread response, keep that ID if follow-ups are expected; otherwise start a new thread.

book_appointment

Book an appointment for a customer. Times are ISO-8601 with timezone, e.g. '2026-07-22T08:00:00+02:00'. Pick times from get_appointment_slots. Omit instructor_ids to book the first available instructor; pass one to request a specific trainer. Validate with validate_appointment_booking first.

book_class_slot

Book a class slot for a customer. Use validate_class_booking first if you are unsure the slot is bookable.

book_trial_appointment

Book a trial-offer appointment for a lead customer. Times are ISO-8601 with timezone; pick them from get_trial_offer_appointment_slots.

book_trial_class

Book a trial-offer class slot for a lead customer (create the lead with create_trial_lead first).

cancel_appointment_booking

Cancel an existing appointment booking by its booking ID.

cancel_class_booking

Cancel an existing class booking by its booking ID.

cancel_contract

**Destructive, never pre-approved; a human confirms every call.** Create an ordinary contract cancelation for a customer. cancelation_date is YYYY-MM-DD; get valid reason IDs from get_contract_cancelation_reasons. This is a real cancelation, confirm details with the user first.

check_in_customer

Create a manual studio check-in for a customer. Optional ISO-8601 time (e.g. '2026-07-17T10:15:30+01:00'); defaults to now.

check_out_customer

Create a manual studio checkout for a customer. Optional ISO-8601 time; defaults to now.

confirm_trial_booking

Confirm a trial offer booking. Required when the trial config sets a confirmationOfBookingTerm, unconfirmed bookings are auto-cancelled after the deadline. Returns CONFIRMED, or EXPIRED if confirmed too late.

create_communication_thread

Log a past communication/interaction on a customer's record as a new thread (e.g. record a phone call or email that happened). NOT for notes on the customer's profile, for profile notes or custom fields (e.g. 'front desk notes') use set_additional_information_fields instead. Threads cannot be read back through this API (write-only). communication_channel: PHONE, EMAIL, CHAT, CONVERSATION, LETTER, TEXT_MESSAGE, FAX or OTHER; communication_direction: INCOMING or OUTGOING; thread_status: CREATED, ONGOING or CLOSED.

create_customer

Create a new customer (prospect, no contract). date_of_birth is YYYY-MM-DD; country_code and language_code are ISO codes (e.g. 'DE', 'de'); gender is MALE, FEMALE or UNISEX. Address is mandatory in Magicline.

create_idle_period

Freeze or pause a membership: create an idle period (hold) on a contract. start_date is YYYY-MM-DD; temporal_unit must be the temporalUnit from get_idle_period_config, with term_value, or set unlimited=true instead. Get valid reason IDs from get_idle_period_config. Run validate_idle_period first.

create_lead

Create a new lead (prospect). gender is MALE, FEMALE or UNISEX; date_of_birth is YYYY-MM-DD. Check get_lead_config for required fields.

create_tax_advisor_export

**Destructive, never pre-approved; a human confirms every call.** Create a tax advisor export. The payload follows the Magicline 'Create tax advisor export' schema (period, export options).

create_trial_lead

Create a lead customer for a trial offer, mandatory before booking a trial session; returns the customerId to book with. Get the trial_offer_config_id from the bookable trial class/appointment, and check get_trial_offer_config for which fields the studio requires. Studios typically reject duplicates by email (DUPLICATE_CUSTOMER).

preview_idle_period_update

Preview the charges/fees of changing an existing idle period (pause/freeze), without applying it, e.g. what extending or shortening a freeze would cost. Use end_date to shorten to an exact date (if the config allows it).

set_additional_information_fields

Set a customer's additional information field values (custom profile fields), THE tool for putting notes on a customer's profile (e.g. a 'Front desk notes' field), not create_communication_thread (which logs a phone call/email interaction instead). assignments is a list of {"additionalInformationFieldId": <id>, "value": <string>}. This REPLACES the customer's full set of assignments, include every field that should keep its value (current values are in get_customer's additionalInformationFieldAssignments; field IDs come from list_additional_information_fields). To append to an existing note, send the old value plus the new text.

signup_membership

**Destructive, never pre-approved; a human confirms every call.** Sign up a brand-new member: creates the customer AND a REAL, binding membership contract in one step, confirm details with the user first. Always run preview_membership_signup first: this works directly only when the preview's dueOnSigningAmount is 0 (nothing to charge at signing). If it is greater than 0, the signup must go through the studio's payment frontend instead, tell the user rather than attempting it. customer follows the same schema as preview_membership_signup (at minimum firstName, lastName, dateOfBirth, email, street, city, zipCode, countryCode and language {"languageCode": ...}). For an EXISTING customer use add_membership, not this. Get term IDs from get_membership_offer.

update_communication_preferences

..., "active": bool, "customerOverridable": bool}]}. Read the current preferences first, modify, and send the result back.

update_idle_period

Change an existing idle period / freeze (extend, shorten, move, or convert an unlimited freeze to a fixed end). Run preview_idle_period_update first to show the customer the resulting charges.

use_customer_benefit

Record a usage of a customer's benefit (consumes one unit of their contingent). Check get_customer_benefits first.

validate_additional_module

Check whether an additional module could be added to a contract, without purchasing it. IDs come from get_purchasable_additional_modules.

validate_appointment_booking

Check whether an appointment can be booked for a customer without booking it, some appointments are restricted to certain memberships. Use before book_appointment. The response carries valid: true/false alongside the raw validationStatus.

validate_class_booking

Check whether a class slot can be booked for a customer, without booking it. The response carries valid: true/false alongside the raw validationStatus.

validate_idle_period

Check whether an idle period (pause/freeze/hold) request is valid, catches overlaps, max-term violations and too-early start dates, without creating it. Use before create_idle_period. validationStatus IDLEPERIOD_CREATABLE means the request is valid (also flagged as valid: true). temporal_unit must be exactly the temporalUnit from get_idle_period_config (e.g. a DAY-based contract rejects MONTH with IDLEPERIOD_TEMPORALUNIT_INVALID).

validate_lead

Validate lead data against the studio's lead config without creating it.

validate_trial_appointment_booking

Check whether a trial-offer appointment can be booked for a lead customer, without booking it. Use before book_trial_appointment. The response carries valid: true/false alongside the raw validationStatus.

validate_trial_class_booking

Check whether a trial class slot can be booked for a lead customer, without booking it. Use before book_trial_class. The response carries valid: true/false alongside the raw validationStatus.

validate_trial_lead

Validate trial-lead data against the trial offer config without creating the lead, catches missing required fields and duplicate customers. Use before create_trial_lead. The response carries valid: true/false alongside the raw validationStatus.

withdraw_contract_cancelation

Withdraw (undo) an ordinary cancelation of a customer's contract.

withdraw_idle_period

Withdraw (cancel) a scheduled idle period / freeze that hasn't started yet. Withdrawn idle periods cannot be reactivated, a new one must be created.

Ask the data warehouse.
In plain language.

Operators with access to the Magicline enterprise data warehouse (Amazon Redshift) get six extra SQL analytics tools: churn, revenue, attendance, any question your studio data can answer. The setup wizard asks once; skip it and nothing changes, the warehouse tools only exist when a connection is configured.

Guardrails on every query

Queries run in read-only transactions that are always rolled back, with a 60-second statement timeout. Results are capped at 500 rows with an honest truncated flag, multi-statement SQL is rejected, and driver errors come back cleaned up with corrective hints for common Redshift-dialect mistakes.

Member data stays masked

At read tier, warehouse_query masks values in string columns and known personal-data columns as "<withheld>", row counts and structure stay truthful, while status columns and period labels stay visible. Unmasked rows require the pii tier via warehouse_query_pii. The masking is best-effort hygiene, not a security boundary: the database user's read-only grants are the real enforcement.

The server teaches the AI

A key-tables cheat sheet is embedded in the server instructions, and the full business glossary (definitions, join keys, correct status filters) is available on demand, by topic through warehouse_docs, or wholesale as MCP resources. The assistant learns the schema before it writes SQL.

six tools, two tiers
# read tier, always on when configured
warehouse_docs            glossary topic lookup
warehouse_list_schemas    queryable schemas
warehouse_list_tables     tables in a schema
warehouse_describe_table  columns and types
warehouse_query           SQL, PII masked

# pii tier, opt-in
warehouse_query_pii       SQL, unmasked rows
password in the OS keyring
# store / inspect / remove the password
uvx magicline-mcp warehouse set
uvx magicline-mcp warehouse status
uvx magicline-mcp warehouse delete

Connect with a read-only warehouse userThe 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, grant it SELECT and nothing else.

Every command, one table.

Run these with uvx magicline-mcp <command> from anywhere, uv fetches the published package from PyPI on demand.

CommandWhat it does
setupOne-time interactive setup (safe read-only mode)
setup --advancedSetup with elevated capabilities (member data, writes, optional per-tool fine-tuning)
setup --auto-updateClients always launch the latest published version
setup --claude-codeAlso configures Claude Code via claude mcp add
setup --allow-allPre-approve tools in Claude Code, writes included, but destructive contract/payment actions still ask
testVerify stored credentials against the live API
toolsList every tool, grouped by permission tier
permissionsChange tiers or enable/disable individual tools, across all configured clients
keys listShow stored keys (masked), environments, active tenant
keys addStore a key for another studio
keys activate <tenant>Switch all clients to another studio (and its environment)
keys delete <tenant>Remove a stored key
warehouse set\|status\|deleteManage the data-warehouse password in the OS keyring
magicline-mcpRun the MCP server on stdio, your AI client does this for you

Keys stored safely.
Studios switched instantly.

Never in a config file

Actual key values live in your OS secret store: macOS Keychain, Windows Credential Manager (DPAPI), or Secret Service on Linux. Only tenant names are kept in ~/.magicline-mcp/tenants.json. On headless Linux without a keyring, fall back to the MAGICLINE_API_KEY environment variable.

One key per studio

Magicline keys are per studio. Multi-studio operators store one key per tenant and switch with keys activate, which rewrites MAGICLINE_TENANT across every configured client at once. Each key remembers its environment (production, sandbox, or a custom URL), so activating a tenant switches the endpoint with it. Restart your client afterwards.

manage stored keys
# list keys (masked) + active tenant
uvx magicline-mcp keys list

# add another studio (validated live)
uvx magicline-mcp keys add

# switch every client to another studio
uvx magicline-mcp keys activate <tenant>

# remove a stored key
uvx magicline-mcp keys delete <tenant>

Prefer to wire it by hand?

The wizard edits these files for you, but every client uses the same format, so you can also edit them yourself.

recommended: key from the keyring
{
  "mcpServers": {
    "Magicline": {
      "command": "uvx",
      "args": ["magicline-mcp"],
      "env": {
        "MAGICLINE_TENANT": "mystudio",
        "MAGICLINE_TOOLS": "read"
      }
    }
  }
}
alternative: key via env var (CI / Docker)
{
  "mcpServers": {
    "Magicline": {
      "command": "uvx",
      "args": ["magicline-mcp"],
      "env": {
        "MAGICLINE_TENANT": "mystudio",
        "MAGICLINE_TOOLS": "read,pii",
        "MAGICLINE_API_KEY": "your-api-key"
      }
    }
  }
}

Let the wizard write these filesOn Windows it writes the full path to uvx.exe as command, since GUI apps don't reliably inherit your shell's PATH, and with --auto-update it writes magicline-mcp@latest so clients always launch the newest release. You don't need to think about any of it.

Environment variables

Variables marked managed are written by the wizard; you only set them yourself in non-interactive environments.

VariableManagedDescription
MAGICLINE_TENANTmanagedYour tenant/studio name: the <tenant> in the base URL. Required.
MAGICLINE_TOOLSmanagedEnabled tiers, comma-separated: read (default), pii, write. read is always included.
MAGICLINE_TOOLS_EXCLUDEmanagedIndividual tools to disable, comma-separated names. Applied after tier filtering; unknown names are ignored with a warning. Managed by magicline-mcp permissions.
MAGICLINE_API_KEY-API key. Overrides the keyring, for CI, Docker or headless machines.
MAGICLINE_BASE_URLmanagedCustom API base URL: written when you pick a sandbox or custom environment. HTTPS required (plain http only for localhost).
WAREHOUSE_HOSTmanagedRedshift endpoint of the enterprise data warehouse. Warehouse tools register only when host, database and user are all set.
WAREHOUSE_PORTmanagedWarehouse port (default 5439).
WAREHOUSE_DATABASEmanagedWarehouse database name.
WAREHOUSE_USERmanagedWarehouse user, use one with read-only grants.
WAREHOUSE_PASSWORD-Warehouse password. Overrides the OS keyring, only needed where no keyring exists.

Considerations & best practices.

  • Use AI tools your organisation approves, and access Magicline data in line with your policies, the integrity of your studio data is yours to monitor.
  • API calls share the same rate limits as every other consumer, heavy use competes for the same budget. Prefer narrow date ranges; broad queries can be throttled.
  • A 403 can mean the member opted out of third-party data access. That's their right; the server reports it rather than retrying.
  • The Open API reads and books against inventory, it can't create it. Classes, appointment types and offers are configured in the Magicline back office.
  • Always validate before booking: classes can be restricted to specific memberships, so a free-looking slot may not be bookable for that member.
  • Keep the least-privileged tier set you can; test writes in a sandbox before production, and query data never persists on the server.

Troubleshooting.

SymptomFix
“No API key found”Run setup, or set MAGICLINE_API_KEY. Verify with test.
401 UnauthorizedTenant and key don't match, or the integration was deactivated. Both come from the same activation email.
403 Permission deniedMissing API-key scope, entity from another studio, or the member opted out of third-party access; the message says which.
Tools missingMember-data and write tools only appear when their tier is on, and individual tools may be disabled: check permissions, then restart the client.
“Server disconnected” (Claude Desktop)Check ~/Library/Logs/Claude/mcp-server-Magicline.log, the last Python traceback usually names the cause.
Keyring issues on LinuxHeadless machines often have no Secret Service; use the MAGICLINE_API_KEY env var in the client config.