Skip to main content

tourclaim (Python CLI, SDK and MCP server)

Python SDK and command-line client for TourClaim by Copernican. Give your app, assistant, or terminal a travel-claim workflow: save a traveler’s answers, collect the evidence they choose to share, hand them the authorization to sign, and follow their claim. Works with any assistant that can run shell commands or call the API; no enrolled tour operator or booking-platform integration is required.

Review mode. The TourClaim connector API currently runs in review mode: it creates synthetic claims and files nothing with an insurer. Use fictional booking and medical data only. tourclaim status (or Client().connector_info()["mode"]) shows the current mode, and every draft and claim the API returns says which mode it came from.

This is the Python edition of tourclaim. It has the same commands, flags, output, exit codes and credentials file as the Node edition (npx tourclaim), so a key saved by one works in the other. It adds a typed library, tourclaim.Client, and an optional MCP server.

For developers, agents, and platforms

TourClaim’s service reviews credit-card travel benefits, organizes receipts and cancellation evidence, coordinates medical-provider evaluation when needed, and handles claim preparation, filing, and follow-up. A traveler can bring a flight, hotel, or tour booking directly. Coverage, reimbursement, and clinical documentation depend on the relevant benefit administrator or provider.

The package exposes saved intake, selected email and file evidence, traveler authorization, submission to Copernican, and status. The API and both CLI editions currently use synthetic review mode: no insurer filing, payment, or clinical service is triggered. To start a real claim today, the traveler uses the online claim form, where they supply their documents and payment details securely.

  • Terminal agents: use either CLI with --json; the traveler approves sign-in and signs in their own browser.
  • Python applications: use tourclaim.Client from the Python edition.
  • Platforms and tool-calling assistants: use the developer guide and OpenAPI schema.

Muse is one integration of these capabilities and is under review; it is not required to use this package. Existing /muse URLs and key formats are compatibility details and continue to work. Each connection acts for one traveler, not an operator or a platform-wide account.

What it does

  1. Sign in. The traveler opens the sign-in page in their own browser, types the code shown in the terminal, and approves. The tool saves a key that belongs to that traveler.
  2. Start a draft with whatever the traveler has said, then answer the questions the API says are still open.
  3. Add evidence the traveler chooses to share: receipts, itineraries, a doctor's note they already have, and booking or cancellation emails.
  4. The traveler signs. They review the draft and sign an authorization in their own browser. This package cannot sign for them.
  5. Submit the signed draft, then check the claim's status.

Nothing here decides whether a loss is covered, or promises reimbursement or a medical note. Copernican charges a 10% fee only when a claim is reimbursed; no payment is taken through this package. Only bookings charged in US dollars are supported.

AI agents: read AGENTS.md before driving the command line. The rules there apply to the library too.

Install

The CLI and SDK require Python 3.9 or newer and have no runtime dependencies. The optional MCP extra requires Python 3.10 or newer and installs the MCP SDK.

pip install tourclaim

or run it without installing, or install it as an isolated command:

uvx tourclaim --help
pipx install tourclaim

python -m tourclaim works too.

MCP server for AI assistants

With uv installed, add this to an MCP client's configuration (Claude Desktop, Cursor, and clients using mcpServers):

{
  "mcpServers": {
    "tourclaim": {
      "command": "uvx",
      "args": ["--python", "3.12", "--from", "tourclaim[mcp]==0.2.0", "tourclaim", "mcp"]
    }
  }
}

Or install pip install 'tourclaim[mcp]==0.2.0' in a Python 3.10+ environment and configure that environment's tourclaim executable with args: ["mcp"]. MCP uses stdio; it waits for a client, and does not print a welcome message to stdout. The server exposes 17 tools with input schemas and read/write annotations. No API key is required to start: the assistant can begin a browser sign-in at the traveler's request. The credential stays in the local credentials store and is never returned to the model.

The current service is in review mode. Use fictional data only. The traveler must approve evidence sharing and sign the authorization in their own browser. See MCP.md for the tool list, VS Code and GitHub configurations, troubleshooting, and transport limitations.

Command line quickstart

# 1. Connect to the traveler's account. Opens a page; the traveler enters the code shown.
tourclaim login

# 2. Find the card the booking was paid with (by product name, never a card number).
tourclaim cards search sapphire

# 3. Start a draft with what the traveler has said so far (check `tourclaim intake list` first).
tourclaim intake start --set merchant_name="Example Air" --set booking_ref=EXA-482913 \
  --set reason_category=airline_cancellation

# 4. Answer what is missing. The draft id comes from step 3.
tourclaim intake set <id> trip_date=2026-03-04 booking_amount=250.00 refunded_amount=50.00 \
  currency=USD card_product_id=412 other_insurance=no \
  narrative="Example Air cancelled flight EX 204 the night before departure."

# 5. Add the evidence the traveler agreed to share.
tourclaim intake attach <id> receipt.pdf --type receipt
tourclaim intake add-email <id> --eml cancellation.eml

# 6. The traveler reviews and signs in their browser. --wait returns once they have.
tourclaim intake sign <id> --wait

# 7. Submit, then follow the claim.
tourclaim intake submit <id>
tourclaim claims list

Every ordinary CLI command takes --json (one JSON value per line on stdout, errors as one JSON line on stderr), --api-url <url>, -h/--help and --version. The full command reference, the field table and the JSON output contract are in the main README; they apply unchanged.

Command What it does
tourclaim login Sign in: the traveler opens the sign-in page and types the code shown in the terminal (--no-browser, --scope, --force). Or --with-token to save an existing key read from stdin or a hidden prompt; such a key does not say whose account it is.
tourclaim logout Revoke the key on the server and remove the stored copy.
tourclaim status (whoami) The API mode, whether the connector is enabled, the signed-in account and key expiry.
tourclaim cards search <name> Find a card product id.
tourclaim intake start|list|show|set|attach|add-email|sign|submit|delete The whole draft lifecycle.
tourclaim claims list|show Submitted claims and their status.
tourclaim mcp Optional MCP stdio server; install the mcp extra. It uses the MCP protocol, not the CLI JSON format.
tourclaim schema The live OpenAPI document with every operation the CLI uses (openapi-cli.json; openapi.json on older servers).

Exit codes

Code Meaning
0 Success.
1 Error: invalid values (422), unreadable or unsupported file, network failure, timeout, declined prompt.
2 Usage: bad flags or arguments, or a confirmation was needed and there was no terminal.
3 Not signed in, or the key was rejected (401) or lacks permission (403). Also a declined or expired sign-in.
4 Conflict (409). The JSON error code names the cause: stale_revision, approval_required, approval_outdated, intake_incomplete, intake_submitted, duplicate_booking, evidence_conflict, idempotency_key_reused, idempotency_key_other_connection or concurrent_request.
5 Rate limited (429) after one automatic retry.
6 Not found (404).
7 The connector is disabled or unavailable (503).

Library quickstart

from tourclaim import Client

# Uses TOURCLAIM_API_KEY, else the key `tourclaim login` saved. Or pass api_key=...
client = Client()

if not client.has_api_key:
    # The traveler opens the page and types the code in their own browser; never put
    # the code in a link. save=True stores the key where `tourclaim login` keeps it.
    client.device_login(
        on_code=lambda code: print(f"Open {code['verification_uri']}\nEnter this code on that page: {code['user_code']}"),
        save=True,
    )

# account_email is present only for keys from `tourclaim login` (device_login).
print(client.get_connection().get("account_email"), client.connector_info()["mode"])

drafts = client.list_drafts()  # offer to continue one before starting another
draft = client.start_intake({"merchant_name": "Example Air", "reason_category": "AIRLINE_CANCELLATION"})
print(draft["missing_fields"], draft["next_questions"])

draft = client.update_intake(
    draft["id"],
    {
        "booking_ref": "EXA-482913",
        "trip_date": "2026-03-04",
        "booking_amount": "250.00",
        "refunded_amount": "50.00",
        "currency": "USD",
        "card_product_id": client.search_cards("sapphire preferred")[0]["id"],
        "narrative": "Example Air cancelled flight EX 204 the night before departure.",
        "other_insurance": "NO",
    },
    expected_revision=draft["revision"],
)

# Only after the traveler agreed to share this exact file:
with open("receipt.pdf", "rb") as f:
    draft = client.add_attachment(
        draft["id"], expected_revision=draft["revision"], filename="receipt.pdf",
        content=f.read(), doc_type="receipt", user_authorized_sharing=True,
    )

# The traveler signs at draft["review_url"] in their own browser.
print("Review and sign:", draft["review_url"])
signed = client.wait_for_signature(draft["id"], timeout=900)

claim = client.submit(draft["id"], expected_revision=signed["revision"])
print(claim["status"], claim["next_action"])

Client(api_key=None, api_url=None) has one method per API operation:

Method Operation
connector_info(), schema() Discovery and the OpenAPI document (no key needed).
get_connection(), disconnect() get_connection, disconnect: the key's account, expiry and scopes; revoke it.
search_cards(query) search_credit_cards
start_intake(fields=None, *, idempotency_key=None) start_travel_claim
list_drafts(offset=0) list_claim_drafts
get_intake(id), update_intake(id, fields, *, expected_revision), delete_draft(id) Read, change and delete a draft.
add_email(id, *, expected_revision, subject, sender, text, user_authorized_sharing, ...) import_selected_email
add_attachment(id, *, expected_revision, filename, content, doc_type, user_authorized_sharing) import_claim_attachment
submit(id, *, expected_revision) submit_authorized_travel_claim (safe to retry)
list_claims(offset=0), get_claim(id) list_my_claims, get_my_claim_status
device_login(scopes=None, *, on_code=None, save=False) Sign in with a device code (also request_device_code, poll_device_token, wait_for_device_token).
wait_for_signature(id, *, timeout=900) Poll until the traveler has signed.

Responses are plain dict objects described by typed dictionaries (IntakeResponse, ClaimResponse, CardResponse, KeyInfo, ...). After each call, client.mode holds the API's mode (review or live).

Errors

Every exception derives from tourclaim.TourClaimError and carries message, code (stable, machine-readable), status (the HTTP status, or None), exit_code (what the command line would exit with) and extra. API errors (APIError) also carry detail and headers.

Exception When
AuthenticationError (401), PermissionDeniedError (403), NotSignedInError The key is missing, expired, revoked or lacks the permission.
NotFoundError (404) No such draft or claim for this key.
ConflictError (409) code is the API's cause from X-TourClaim-Error, such as stale_revision or approval_required.
ValidationError (422) detail lists each invalid field as {loc, type, msg}, or explains in a sentence.
RateLimitError (429) retry_after seconds. The client retries once by itself when that is at most 60.
UnavailableError (503) The connector is disabled or temporarily unavailable.
NetworkError, RequestTimeoutError The API could not be reached, or did not answer in 90 seconds.
AccessDeniedError, ExpiredTokenError The traveler declined the sign-in, or its code expired.
ConsentRequiredError, UnsupportedFileError, FileTooLargeError, UsageError Checked before anything is sent.

Configuration

Variable Meaning
TOURCLAIM_API_URL API base URL (default https://app.getcopernican.com). --api-url overrides it. Plain http:// is accepted only for localhost.
TOURCLAIM_API_KEY A key to use instead of the stored one. It takes precedence over the stored key.
XDG_CONFIG_HOME Credentials are stored in $XDG_CONFIG_HOME/tourclaim/credentials.json (default ~/.config/tourclaim/credentials.json; %APPDATA%\tourclaim\credentials.json on Windows).

The credentials file maps each API base URL to {"api_key","expires_at","grant_id","scopes"} and is shared with the Node edition.

Security

  • Keys belong to one traveler. A key lasts 30 days and cannot be refreshed; a traveler can have at most 5 connections, and a new tourclaim login past that retires the account's oldest tourclaim login key (never another app's). Keys from tourclaim login reach the drafts started by any tourclaim login on the same account, so signing in again does not lose a draft. The traveler can revoke keys at https://app.getcopernican.com/connect/muse, and tourclaim logout revokes the one in use.
  • Stored with tight permissions. The credentials file is written with mode 0600 inside a 0700 directory, and the tool warns if it is readable by others. On Windows it lives in your user profile and relies on its permissions.
  • The code is typed, never linked. The traveler types the code shown in the terminal (or relayed by an assistant they are using right now) on the sign-in page; there is no link with the code in it. A sign-in that replaces a stored key sends that key along, and the server retires it as it issues the new one.
  • Never on the command line, never printed. Keys are not accepted as arguments, and anything shaped like a key is redacted from output. repr(Client(...)) does not show the key.
  • Only https. Keys are only sent over https, except to localhost for testing. Redirects are not followed.
  • A person signs. Only the traveler can sign the claim authorization, in their own browser at the review link. Neither the command line nor the library can sign.
  • Sharing needs consent. Files and emails are uploaded only after the traveler agrees: at a prompt or with --yes on the command line, and with user_authorized_sharing=True in the library. There is no default that shares.
  • Evidence is not instructions. Email and file contents are stored as evidence. Neither the API nor this package follows instructions found in them.

To report a vulnerability, see SECURITY.md.

Development

cd python
python -m venv .venv && .venv/bin/pip install -e ".[dev]"
.venv/bin/python -m pytest
.venv/bin/python tests/mock_server.py   # a mock API on http://127.0.0.1:4010 for trying the tool by hand

The tests run the command line in-process and as a child process against a mock of the API built on http.server. Releases are described in RELEASING.md.

License

MIT

Metadata

Release files for tourclaim 0.2.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for tourclaim 0.2.0
File Size Uploaded
tourclaim-0.2.0.tar.gz 115.9 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for tourclaim 0.2.0
File Interpreter ABI Platform
tourclaim-0.2.0-py3-none-any.whl Python 3 none any Details

Total release size: 193.3 kB

Release files / tourclaim-0.2.0.tar.gz

Download URL tourclaim-0.2.0.tar.gz
Size 115.9 kB
Tags Source
SHA-256 checksum
How to use checksums
7b948b36649eea6af95a2923ea63453f2df514e0003f3202d1393f69b137dcc6
BLAKE2b-256 checksum
How to use checksums
9f3888f2267269a883b2cecc68c5cf70c6e47a2a487270f8bea62da9e0048ea8
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release files / tourclaim-0.2.0-py3-none-any.whl

Download URL tourclaim-0.2.0-py3-none-any.whl
Size 77.4 kB
Tags Python 3
SHA-256 checksum
How to use checksums
8c85aab6d981f2eb495fe3fffb5f2cf1943566149ee73789d376c5e708274635
BLAKE2b-256 checksum
How to use checksums
4f960d2889eef3331d5b4e865a8ed00ffe5ef034aeb79e707b48e07f0cf5960b
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Oct 6, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.2.0 This release

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page