Koskamo

Upgrade Agent MCP

An MCP server that enables AI agents to programmatically check eligibility, place bids, modify or cancel upgrade offers, and confirm instant travel upgrades for airlines, cruises, and rail operators via a secure API.

Endpoint and access

No sign-in to connect and list tools. Individual tools may still need a vendor account, credentials, or permissions; check the documented prerequisites.

Upgrade Agent MCP logo, by PlusgradeVendor evidenceStreamable HTTPNo sign-inEndpoint checked 2026-11-07Operated by Plusgrade
You need:Authentication: OAuth 2.1 (PKCE, dynamic client registration at POST /api/oauth/register) or a bearer token.
MCP endpoint (Streamable HTTP)
https://www.upgradeagent.ai/api/mcp
Vendor documentation

What its tools do

21 tools, grouped by the hints the server advertises. Hints are self-declared, not verified behavior.

21 of 21 have a description · 21 of 21 declare behavior hints · 16 of 20 with parameters document them all

Checks and signals

Each line is separate evidence, not a trust score.

  • Passed Endpoint answered the live check ·
  • Passed Official MCP Registry namespace is tied to upgradeagent.ai ·
  • Passed Endpoint is on the registry namespace domain ·
  • Availability 1 of 1 checks passed in 30 days

What you can do with it

  • Check upgrade eligibility and bid ranges for a specific booking
  • Place or modify a bid for a cabin upgrade
  • Cancel a pending upgrade offer
  • Confirm an instant upgrade purchase

Source and maintenance

Vendor evidenceRegistry 1.1.0
Maintenance checked

Protocol and capabilities

Server
upgrade-agent 1.0.0
MCP protocol negotiated in check
2025-11-25
Tools
21 advertised
Resources
13 advertised
Resource templates
0 advertised
Prompts
Not advertised
Server-advertised capabilities
{
  "tools": {
    "listChanged": true
  },
  "resources": {
    "listChanged": true
  }
}

Server-provided instructions

Untrusted server output shown for inspection. It is not Koskamo guidance and is excluded from knowledge search.

Upgrade Agent covers flight, cruise, and rail UPGRADES — bid (offer) upgrades, instant upgrades, and points upgrades — across ~90 airlines and operators, with live, booking-specific eligibility rather than general estimates. Tools: - start_eligibility_check: opens a secure page (and inline form where supported) for a traveler to check a booking; booking details stay off the transcript. Carrier optional. - check_upgrade_eligibility: looks up a booking directly from a reference, last name, and airline already shared in the conversation. - get_eligibility_result: reads the outcome of a completed check by sessionId. - get_upgrade_pricing: typical bid ranges per cabin for an operator (no booking needed). - predict_bid_success: how likely a specific bid amount is to be accepted. - place_bid / modify_bid / get_bid_status / cancel_bid: prepare, change, review, or withdraw a bid on a checked booking; payment is completed on the operator's secure page. - get_price_breakdown: itemized all-in cost of a bid before committing. - start_watch / get_watch_status: watch a booking over time for upgrade opportunities. - ask_upgrade_agent, get_partner_info, list_partners, search_upgrade_options: general upgrade questions, a specific operator's program, and finding operators that offer upgrades. Booking details and consent are collected on the secure page or card, not in the chat. Passing a stable conversationId across calls lets follow-ups reuse the operator and checked booking.

Tools

21 advertised

check_upgrade_eligibility — Check Booking Eligibility
Advertised by the server during the last successful anonymous check.
Open-world

Looks up a booking's upgrade eligibility from a booking reference and last name, and airline. Returns eligibility status, upgrade options, bid ranges, and a session id for follow-up bid tools.

check_upgrade_eligibility input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "pnr",
    "lastName"
  ],
  "properties": {
    "pnr": {
      "type": "string",
      "description": "The booking reference or PNR (e.g. ABC123)."
    },
    "carrier": {
      "type": "string",
      "description": "Airline/cruise/rail name or IATA code (e.g. 'SWISS' or 'LX')."
    },
    "language": {
      "type": "string",
      "description": "ISO 639-1 language for the offer page (e.g. 'fr', 'es'). Defaults to 'en'."
    },
    "lastName": {
      "type": "string",
      "description": "Passenger last name, exactly as it appears on the booking."
    },
    "intentContext": {
      "type": "object",
      "properties": {
        "notes": {
          "type": "string",
          "maxLength": 200,
          "description": "Short preference note, e.g. 'anniversary trip, wants lie-flat'. For privacy, leave out booking references and names."
        },
        "budgetAmount": {
          "type": "number",
          "description": "Traveler's stated budget for the upgrade.",
          "exclusiveMinimum": 0
        },
        "budgetCurrency": {
          "type": "string",
          "maxLength": 3,
          "description": "ISO currency for the budget, e.g. 'CAD'."
        },
        "preferredCabin": {
          "enum": [
            "BUSINESS",
            "FIRST",
            "PREMIUM_ECONOMY"
          ],
          "type": "string"
        }
      },
      "description": "The traveler's stated shopping intent — bound to the session and surfaced back so offers are presented against it.",
      "additionalProperties": false
    },
    "conversationId": {
      "type": "string",
      "description": "Optional stable conversation id — lets place_bid/modify_bid reuse this booking."
    },
    "travelerQuestion": {
      "type": "string",
      "description": "The traveler's request in their own words, verbatim (e.g. 'can I upgrade my Swiss flight to business?'). For privacy, leave out the booking reference, last name, email, and other personal details. Pass it whenever the traveler asked in free text — it improves the assistant's answers over time."
    }
  },
  "additionalProperties": false
}
check_upgrade_eligibility annotations
{
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
start_eligibility_check — Start Eligibility Check
Advertised by the server during the last successful anonymous check.

Starts an upgrade eligibility check for a flight, cruise, or rail booking. Returns a secure page (and, where supported, an inline form) for the traveler to enter their booking reference and last name.

start_eligibility_check input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "carrier": {
      "type": "string",
      "description": "Airline/cruise/rail name or IATA code if known (e.g. 'Air Canada' or 'AC')."
    },
    "language": {
      "type": "string",
      "description": "ISO 639-1 language for the page/offer (e.g. 'fr', 'es'). Defaults to 'en'."
    },
    "intentContext": {
      "type": "object",
      "properties": {
        "notes": {
          "type": "string",
          "maxLength": 200,
          "description": "Short preference note, e.g. 'anniversary trip, wants lie-flat'. For privacy, leave out booking references and names."
        },
        "budgetAmount": {
          "type": "number",
          "description": "Traveler's stated budget for the upgrade.",
          "exclusiveMinimum": 0
        },
        "budgetCurrency": {
          "type": "string",
          "maxLength": 3,
          "description": "ISO currency for the budget, e.g. 'CAD'."
        },
        "preferredCabin": {
          "enum": [
            "BUSINESS",
            "FIRST",
            "PREMIUM_ECONOMY"
          ],
          "type": "string"
        }
      },
      "description": "The traveler's stated shopping intent — bound to the session and surfaced back so offers are presented against it.",
      "additionalProperties": false
    },
    "travelerQuestion": {
      "type": "string",
      "description": "The traveler's request in their own words, verbatim (e.g. 'can I upgrade my Swiss flight to business?'). For privacy, leave out the booking reference, last name, email, and other personal details. Pass it whenever the traveler asked in free text — it improves the assistant's answers over time."
    }
  },
  "additionalProperties": false
}
start_eligibility_check annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
mint_eligibility_session — Mint Eligibility Session (internal)
Advertised by the server during the last successful anonymous check.

Internal helper for the inline eligibility form: creates a secure session and returns its id. No UI; agents should use start_eligibility_check instead.

mint_eligibility_session input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "carrier": {
      "type": "string",
      "description": "Operator name/IATA if known."
    },
    "language": {
      "type": "string",
      "description": "ISO 639-1 language (default 'en')."
    }
  },
  "additionalProperties": false
}
mint_eligibility_session annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
get_eligibility_result
Advertised by the server during the last successful anonymous check.
Advertised read-only

Read the result of a secure eligibility check started with start_eligibility_check. Pass the sessionId returned by that tool. Returns the live eligibility outcome (eligible options, bid ranges, offer URL) once the passenger has submitted their details on the secure page — or a 'still waiting' status if they haven't yet.

get_eligibility_result input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "sessionId"
  ],
  "properties": {
    "sessionId": {
      "type": "string",
      "description": "The sessionId returned by start_eligibility_check."
    },
    "conversationId": {
      "type": "string",
      "description": "Optional stable conversation id — lets later tools (place_bid) reuse this booking without re-passing the sessionId."
    }
  },
  "additionalProperties": false
}
get_eligibility_result annotations
{
  "title": "Get Eligibility Result",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
place_bid — Place Upgrade Bid
Advertised by the server during the last successful anonymous check.
Open-world

Places an upgrade bid, or buys a fixed-price (INSTANT) upgrade, for a checked booking. Takes an eligibility-check session id, an amount (omitted for INSTANT), and a cabin/segment. Returns a secure operator link to complete payment.

place_bid input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "amount": {
      "type": "number",
      "description": "Bid amount in the offer currency (or points for POINTS). OMIT for INSTANT — the airline's fixed price is used automatically."
    },
    "confirm": {
      "type": "boolean",
      "description": "Set true to confirm and commit a REAL bid submission (human-in-the-loop). Only required once live bid submission is enabled; otherwise the bid is staged for secure payment."
    },
    "segment": {
      "type": "string",
      "description": "Route 'YUL-LHR' or flight number, if more than one segment is eligible."
    },
    "quantity": {
      "type": "number",
      "description": "Number of seats (default 1)."
    },
    "sessionId": {
      "type": "string",
      "description": "The sessionId from start_eligibility_check. Optional if conversationId is passed (reuses the last checked booking)."
    },
    "upgradeType": {
      "enum": [
        "BUSINESS",
        "FIRST",
        "PREMIUM_ECONOMY"
      ],
      "type": "string",
      "description": "Target cabin, if the booking has more than one eligible option."
    },
    "purchaseType": {
      "enum": [
        "BID",
        "POINTS",
        "INSTANT"
      ],
      "type": "string",
      "description": "BID (money offer, default), POINTS to redeem loyalty points ('amount' = points), or INSTANT to buy now at the airline's fixed price (no amount needed)."
    },
    "conversationId": {
      "type": "string",
      "description": "Stable conversation id used on get_eligibility_result — lets you bid without re-passing the sessionId."
    },
    "presentationReport": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "offerId",
          "shown"
        ],
        "properties": {
          "shown": {
            "type": "boolean",
            "description": "Whether you actually presented this offer to the traveler."
          },
          "reason": {
            "enum": [
              "REASON_PRICE_CEILING",
              "REASON_LOW_PROBABILITY",
              "REASON_PREFERENCE_CLASH"
            ],
            "type": "string",
            "description": "Why it was filtered or deprioritized — supply when shown=false (over budget → REASON_PRICE_CEILING; low acceptance odds → REASON_LOW_PROBABILITY; conflicts with stated preferences → REASON_PREFERENCE_CLASH)."
          },
          "offerId": {
            "type": "string",
            "description": "The offer id from the eligibility result's 'Offer ids for presentation reporting' line."
          }
        },
        "additionalProperties": false
      },
      "description": "REPORT WHAT YOU SHOWED: if you filtered, hid, or deprioritized ANY offer from the eligibility result before presenting to the traveler, report every offer here with shown + reason. Contains no traveler data; powers partner analytics."
    }
  },
  "additionalProperties": false
}
place_bid annotations
{
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
modify_bid — Modify Upgrade Bid
Advertised by the server during the last successful anonymous check.
Open-world

Change the amount of a bid already prepared/placed on a booking. Same as place_bid but for updating an existing bid — pass the sessionId, the NEW amount, and the cabin/segment if ambiguous. The new amount is validated against the airline's range; payment/confirmation completes on the operator's secure page.

modify_bid input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "amount"
  ],
  "properties": {
    "amount": {
      "type": "number",
      "description": "The NEW bid amount in the offer currency."
    },
    "confirm": {
      "type": "boolean",
      "description": "Set true to confirm and commit a REAL bid update (human-in-the-loop). Only required once live bid submission is enabled."
    },
    "segment": {
      "type": "string",
      "description": "Route 'YUL-LHR' or flight number, if ambiguous."
    },
    "quantity": {
      "type": "number"
    },
    "sessionId": {
      "type": "string",
      "description": "The sessionId from start_eligibility_check. Optional if conversationId is passed."
    },
    "upgradeType": {
      "enum": [
        "BUSINESS",
        "FIRST",
        "PREMIUM_ECONOMY"
      ],
      "type": "string"
    },
    "conversationId": {
      "type": "string",
      "description": "Stable conversation id (reuses the last checked booking)."
    },
    "presentationReport": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "offerId",
          "shown"
        ],
        "properties": {
          "shown": {
            "type": "boolean",
            "description": "Whether you actually presented this offer to the traveler."
          },
          "reason": {
            "enum": [
              "REASON_PRICE_CEILING",
              "REASON_LOW_PROBABILITY",
              "REASON_PREFERENCE_CLASH"
            ],
            "type": "string",
            "description": "Why it was filtered or deprioritized — supply when shown=false (over budget → REASON_PRICE_CEILING; low acceptance odds → REASON_LOW_PROBABILITY; conflicts with stated preferences → REASON_PREFERENCE_CLASH)."
          },
          "offerId": {
            "type": "string",
            "description": "The offer id from the eligibility result's 'Offer ids for presentation reporting' line."
          }
        },
        "additionalProperties": false
      },
      "description": "REPORT WHAT YOU SHOWED: if you filtered, hid, or deprioritized ANY offer from the eligibility result before presenting to the traveler, report every offer here with shown + reason. Contains no traveler data; powers partner analytics."
    }
  },
  "additionalProperties": false
}
modify_bid annotations
{
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
get_bid_status — Get Bid Status
Advertised by the server during the last successful anonymous check.
Advertised read-only

Check any bids already on a booking (submitted / accepted / declined), the bid-eligible cabins with their ranges, and the current cart. Pass the sessionId from start_eligibility_check. In hosts that render app widgets it shows a manage screen inline. Use modify_bid / cancel_bid to change or withdraw a bid.

get_bid_status input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "sessionId": {
      "type": "string",
      "description": "The sessionId from start_eligibility_check. Optional if conversationId is passed."
    },
    "conversationId": {
      "type": "string",
      "description": "Stable conversation id (reuses the last checked booking)."
    },
    "presentationReport": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "offerId",
          "shown"
        ],
        "properties": {
          "shown": {
            "type": "boolean",
            "description": "Whether you actually presented this offer to the traveler."
          },
          "reason": {
            "enum": [
              "REASON_PRICE_CEILING",
              "REASON_LOW_PROBABILITY",
              "REASON_PREFERENCE_CLASH"
            ],
            "type": "string",
            "description": "Why it was filtered or deprioritized — supply when shown=false (over budget → REASON_PRICE_CEILING; low acceptance odds → REASON_LOW_PROBABILITY; conflicts with stated preferences → REASON_PREFERENCE_CLASH)."
          },
          "offerId": {
            "type": "string",
            "description": "The offer id from the eligibility result's 'Offer ids for presentation reporting' line."
          }
        },
        "additionalProperties": false
      },
      "description": "REPORT WHAT YOU SHOWED: if you filtered, hid, or deprioritized ANY offer from the eligibility result before presenting to the traveler, report every offer here with shown + reason. Contains no traveler data; powers partner analytics."
    }
  },
  "additionalProperties": false
}
get_bid_status annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_offer_events — Get Offer Events
Advertised by the server during the last successful anonymous check.
Advertised read-only

Poll for bid-outcome changes on a checked booking without re-running a status check: an ordered log of events (offer.status_changed, offer.accepted, offer.declined, offer.cancelled, checkout.paid) with the offer reference, new and previous status, amount and cabin. Pass the sessionId (or conversationId) and, on later calls, the `since` cursor from the previous response to get only what's new. Bids settle 24–72h before departure, so poll periodically (or subscribe via REST POST /api/v1/webhooks) instead of asking the traveler to check back. Empty means no change observed yet.

get_offer_events input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "limit": {
      "type": "integer",
      "maximum": 200,
      "minimum": 1,
      "description": "Max events to return (default 50)."
    },
    "since": {
      "type": "string",
      "description": "Return only events after this: the `nextCursor` from a previous call, or an ISO-8601 timestamp."
    },
    "sessionId": {
      "type": "string",
      "description": "The sessionId from start_eligibility_check. Optional if conversationId is passed."
    },
    "conversationId": {
      "type": "string",
      "description": "Stable conversation id (reuses the last checked booking)."
    }
  },
  "additionalProperties": false
}
get_offer_events annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_price_breakdown — Get Price Breakdown
Advertised by the server during the last successful anonymous check.
Advertised read-only

Show the itemized all-in cost of an upgrade before the traveler commits — the amount plus any taxes and fees. Pass the sessionId (or conversationId), the amount (omit it for INSTANT — the airline's fixed price is used), and the cabin/segment if the booking has more than one option. For a BID it also returns the operator's own bid-strength read. Use it to answer 'what will this actually cost me?' before place_bid.

get_price_breakdown input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "amount": {
      "type": "number",
      "description": "The amount to price — a bid in the offer currency, or a number of points for purchaseType POINTS. Omit for INSTANT (fixed price)."
    },
    "segment": {
      "type": "string",
      "description": "Route 'YUL-LHR' or flight number, if more than one is eligible."
    },
    "sessionId": {
      "type": "string",
      "description": "The sessionId from start_eligibility_check. Optional if conversationId is passed."
    },
    "upgradeType": {
      "enum": [
        "BUSINESS",
        "FIRST",
        "PREMIUM_ECONOMY"
      ],
      "type": "string"
    },
    "purchaseType": {
      "enum": [
        "BID",
        "POINTS",
        "INSTANT"
      ],
      "type": "string",
      "description": "BID (default), POINTS, or INSTANT (buy now at the airline's fixed price)."
    },
    "conversationId": {
      "type": "string",
      "description": "Stable conversation id (reuses the last checked booking)."
    }
  },
  "additionalProperties": false
}
get_price_breakdown annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
cancel_bid — Cancel Upgrade Bid
Advertised by the server during the last successful anonymous check.
Open-world

Withdraw a bid already placed on a booking the traveler checked with start_eligibility_check. Pass the sessionId (or conversationId). If the booking has more than one bid, pass orderChangeId to say which — get_bid_status lists them. Confirm with the traveler before calling; this releases the bid.

cancel_bid input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "confirm": {
      "type": "boolean",
      "description": "Set true once the traveler has confirmed they want the bid withdrawn."
    },
    "sessionId": {
      "type": "string",
      "description": "The sessionId from start_eligibility_check. Optional if conversationId is passed."
    },
    "orderChangeId": {
      "type": "string",
      "description": "Which bid to cancel, when the booking has more than one (from get_bid_status)."
    },
    "conversationId": {
      "type": "string",
      "description": "Stable conversation id (reuses the last checked booking)."
    },
    "presentationReport": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "offerId",
          "shown"
        ],
        "properties": {
          "shown": {
            "type": "boolean",
            "description": "Whether you actually presented this offer to the traveler."
          },
          "reason": {
            "enum": [
              "REASON_PRICE_CEILING",
              "REASON_LOW_PROBABILITY",
              "REASON_PREFERENCE_CLASH"
            ],
            "type": "string",
            "description": "Why it was filtered or deprioritized — supply when shown=false (over budget → REASON_PRICE_CEILING; low acceptance odds → REASON_LOW_PROBABILITY; conflicts with stated preferences → REASON_PREFERENCE_CLASH)."
          },
          "offerId": {
            "type": "string",
            "description": "The offer id from the eligibility result's 'Offer ids for presentation reporting' line."
          }
        },
        "additionalProperties": false
      },
      "description": "REPORT WHAT YOU SHOWED: if you filtered, hid, or deprioritized ANY offer from the eligibility result before presenting to the traveler, report every offer here with shown + reason. Contains no traveler data; powers partner analytics."
    }
  },
  "additionalProperties": false
}
cancel_bid annotations
{
  "readOnlyHint": false,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
predict_bid_success — Predict Bid Success
Advertised by the server during the last successful anonymous check.
Advertised read-only

Estimates how likely a specific bid amount is to be accepted, grounded in resolved bid outcomes for the carrier cabin, plus the operator's own bid-strength read when a checked booking's session id is provided. Returns null when there isn't enough data.

predict_bid_success input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "amount"
  ],
  "properties": {
    "cabin": {
      "enum": [
        "BUSINESS",
        "FIRST",
        "PREMIUM_ECONOMY"
      ],
      "type": "string",
      "description": "Optional: target cabin."
    },
    "amount": {
      "type": "number",
      "description": "The bid amount to evaluate, in the operator's offer currency."
    },
    "carrier": {
      "type": "string",
      "description": "Operator IATA code or name, e.g. 'LH' or 'Lufthansa'. Optional if conversationId carries the operator from earlier."
    },
    "segment": {
      "type": "string",
      "description": "Route 'YUL-LHR' or flight number, if the booking has more than one bid-eligible segment."
    },
    "sessionId": {
      "type": "string",
      "description": "The sessionId from start_eligibility_check — unlocks the operator's LIVE bid-strength read for this exact booking and amount."
    },
    "conversationId": {
      "type": "string",
      "description": "Optional stable conversation id — reuses the operator (and checked booking) in play."
    },
    "travelerQuestion": {
      "type": "string",
      "description": "The traveler's request in their own words, verbatim (e.g. 'can I upgrade my Swiss flight to business?'). For privacy, leave out the booking reference, last name, email, and other personal details. Pass it whenever the traveler asked in free text — it improves the assistant's answers over time."
    }
  },
  "additionalProperties": false
}
predict_bid_success annotations
{
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
start_watch — Start Booking Watch
Advertised by the server during the last successful anonymous check.

Sets up a Watcher that monitors a traveler's booking between now and departure for upgrade opportunities (a better seat, an empty adjacent seat, a cabin upgrade, lounge, or fast track). Returns a secure card/link where the traveler enters their booking, notification preference, and consent.

start_watch input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "preferences"
  ],
  "properties": {
    "carrier": {
      "type": "string",
      "description": "Airline/operator name or IATA code if known."
    },
    "contact": {
      "type": "object",
      "properties": {
        "email": {
          "type": "string"
        },
        "phone": {
          "type": "string",
          "description": "Mobile number for SMS (E.164, e.g. +14155551234)."
        },
        "whatsapp": {
          "type": "string"
        }
      },
      "additionalProperties": false
    },
    "purpose": {
      "enum": [
        "business",
        "leisure"
      ],
      "type": "string",
      "description": "Is the trip for business or leisure? Tailors the complementary experiences we surface at the destination."
    },
    "channels": {
      "type": "array",
      "items": {
        "type": "string"
      },
      "description": "How to reach them: in_chat | watch_page | email | sms | whatsapp | push."
    },
    "autoAction": {
      "type": "boolean",
      "description": "If true (and a budget is set), act within budget; else notify."
    },
    "firstVisit": {
      "type": "boolean",
      "description": "Is this the traveler's first time at the destination? Biases toward the classics vs off-the-beaten-path."
    },
    "preferences": {
      "type": "array",
      "items": {
        "type": "object",
        "required": [
          "type"
        ],
        "properties": {
          "rank": {
            "type": "number",
            "description": "1 = most wanted."
          },
          "type": {
            "type": "string",
            "description": "e.g. window_seat | aisle_seat | extra_legroom | empty_seat | premium_economy | business_upgrade | first_upgrade | lounge | fast_track"
          },
          "currency": {
            "type": "string"
          },
          "maxAmount": {
            "type": "number",
            "description": "Optional budget cap for this perk."
          }
        },
        "additionalProperties": false
      },
      "description": "The traveler's improvements to watch for, in their order of preference."
    },
    "budgetAmount": {
      "type": "number",
      "description": "Overall budget if they want the agent to act."
    },
    "budgetCurrency": {
      "type": "string"
    }
  },
  "additionalProperties": false
}
start_watch annotations
{
  "readOnlyHint": false,
  "openWorldHint": false,
  "idempotentHint": false,
  "destructiveHint": false
}
get_watch_status
Advertised by the server during the last successful anonymous check.
Advertised read-only

Check a Watcher Concierge watch (created with start_watch). Returns its status, what it's watching for, and any improvements found so far. Pass the token from start_watch.

get_watch_status input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "token"
  ],
  "properties": {
    "token": {
      "type": "string",
      "description": "The watch token returned by start_watch."
    }
  },
  "additionalProperties": false
}
get_watch_status annotations
{
  "title": "Get Watch Status",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
ask_upgrade_agent
Advertised by the server during the last successful anonymous check.
Advertised read-onlyOpen-world

Answer a general (not booking-specific) travel-upgrade question — how bid/instant/points upgrades work, eligibility rules, bidding strategy, and which airlines, cruise lines, or rail operators offer upgrades. Use this for informational questions only. To check a SPECIFIC booking, use start_eligibility_check (preferred — collects PNR + last name on a secure page).

ask_upgrade_agent input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "question"
  ],
  "properties": {
    "askedBy": {
      "type": "string",
      "description": "Identifier for the calling agent/app (e.g. 'claude-cowork', 'aircanada-bot'). Used for per-partner reporting on which agents ask about their brand."
    },
    "question": {
      "type": "string",
      "description": "The traveler's upgrade question, in natural language."
    },
    "conversationId": {
      "type": "string",
      "description": "Optional stable conversation id — carries the operator in play across follow-up questions (e.g. 'what about the return?')."
    }
  },
  "additionalProperties": false
}
ask_upgrade_agent annotations
{
  "title": "Ask Upgrade Agent",
  "readOnlyHint": true,
  "openWorldHint": true,
  "idempotentHint": false,
  "destructiveHint": false
}
partner_question_insights
Advertised by the server during the last successful anonymous check.
Advertised read-only

Per-partner analytics report: what travelers and AI agents are asking about a specific partner's upgrade programs (by intent, by route, most frequent questions, which agents/clients are asking), the AI-check → bid → paid conversion funnel by channel, AI visibility (share of answer per engine, what agents say, where answers are wrong), open content gaps and observed bid ranges. Text summary plus the full report object in structuredContent. Pass the partner name (e.g. 'Air Canada', 'MSC Cruises').

partner_question_insights input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "window": {
      "enum": [
        "7d",
        "30d",
        "90d"
      ],
      "type": "string",
      "description": "Report window (default 30d)."
    },
    "partner": {
      "type": "string",
      "description": "Partner name, slug or IATA code, e.g. 'Air Canada'. Ignored for partner-scoped tokens (locked to their own brand)."
    }
  },
  "additionalProperties": false
}
partner_question_insights annotations
{
  "title": "Partner Question Insights",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
partner_visibility_report
Advertised by the server during the last successful anonymous check.
Advertised read-only

AI visibility for one partner's upgrade program: share of answer across the answer engines (ChatGPT, Claude, Perplexity, Gemini) for prompts about that partner, which domains get cited instead, what the agents say about the program, and where the answers are wrong (community claims that contradict the program's facts, plus engine excerpts flagged for human review). Partner-scoped tokens are locked to their own brand.

partner_visibility_report input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "window": {
      "enum": [
        "7d",
        "30d",
        "90d"
      ],
      "type": "string",
      "description": "Report window (default 30d)."
    },
    "partner": {
      "type": "string",
      "description": "Partner name, slug or IATA code. Ignored for partner-scoped tokens."
    }
  },
  "additionalProperties": false
}
partner_visibility_report annotations
{
  "title": "Partner Visibility Report",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
usage_totals
Advertised by the server during the last successful anonymous check.
Advertised read-only

Running totals across the whole system: how many questions have been asked, and how many were answered successfully (quality at or above the success threshold).

usage_totals input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {}
}
usage_totals annotations
{
  "title": "Usage Totals",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_partner_info
Advertised by the server during the last successful anonymous check.
Advertised read-only

Get the full upgrade profile for one operator — products offered (with the official page URL), loyalty program, cabin paths, how to access, and summary. More detailed than ask_upgrade_agent. Accepts an IATA code or a name (e.g. 'AC' or 'Air Canada').

get_partner_info input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "required": [
    "carrier"
  ],
  "properties": {
    "carrier": {
      "type": "string",
      "description": "Operator IATA code or name, e.g. 'LH' or 'Lufthansa'."
    },
    "travelerQuestion": {
      "type": "string",
      "description": "The traveler's request in their own words, verbatim (e.g. 'can I upgrade my Swiss flight to business?'). For privacy, leave out the booking reference, last name, email, and other personal details. Pass it whenever the traveler asked in free text — it improves the assistant's answers over time."
    }
  },
  "additionalProperties": false
}
get_partner_info annotations
{
  "title": "Get Partner Info",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
get_upgrade_pricing
Advertised by the server during the last successful anonymous check.
Advertised read-only

Returns typical upgrade bid ranges (low / typical / high, per cabin) for an operator, aggregated from anonymized eligibility checks. Accepts an IATA code or a name. With an origin and destination airport, the ranges are scoped to that route when observed data exists there (either direction), otherwise the operator-wide ranges are returned and labelled as such. Says so when there isn't enough observed data.

get_upgrade_pricing input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "cabin": {
      "enum": [
        "BUSINESS",
        "FIRST",
        "PREMIUM_ECONOMY"
      ],
      "type": "string",
      "description": "Optional: limit to one target cabin."
    },
    "origin": {
      "type": "string",
      "description": "Optional origin airport IATA code (e.g. 'YUL') — scopes the ranges to a route."
    },
    "carrier": {
      "type": "string",
      "description": "Operator IATA code or name, e.g. 'LH' or 'Lufthansa'. Optional if conversationId carries the operator from earlier."
    },
    "destination": {
      "type": "string",
      "description": "Optional destination airport IATA code (e.g. 'LHR') — scopes the ranges to a route."
    },
    "conversationId": {
      "type": "string",
      "description": "Optional stable conversation id — reuses the operator in play."
    },
    "travelerQuestion": {
      "type": "string",
      "description": "The traveler's request in their own words, verbatim (e.g. 'can I upgrade my Swiss flight to business?'). For privacy, leave out the booking reference, last name, email, and other personal details. Pass it whenever the traveler asked in free text — it improves the assistant's answers over time."
    }
  },
  "additionalProperties": false
}
get_upgrade_pricing annotations
{
  "title": "Get Upgrade Pricing",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
list_partners
Advertised by the server during the last successful anonymous check.
Advertised read-only

List the travel operators that offer upgrade programs, with optional filters. Returns each operator's name, IATA/code, vertical, region, and the upgrade products it offers. Use this to build travel workflows or answer 'which airlines/cruise lines offer upgrades'.

list_partners input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "region": {
      "enum": [
        "Americas",
        "Europe",
        "MEA",
        "APAC",
        "Cruise",
        "Rail"
      ],
      "type": "string",
      "description": "Filter by region (MEA = Middle East & Africa, APAC = Asia-Pacific)."
    },
    "product": {
      "enum": [
        "bid_upgrade",
        "instant_upgrade",
        "seat_blocker",
        "premium_seating"
      ],
      "type": "string",
      "description": "Only operators that offer this product."
    },
    "vertical": {
      "enum": [
        "airline",
        "cruise",
        "rail",
        "hotel"
      ],
      "type": "string",
      "description": "Filter by operator type."
    }
  },
  "additionalProperties": false
}
list_partners annotations
{
  "title": "List Upgrade Partners",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}
search_upgrade_options
Advertised by the server during the last successful anonymous check.
Advertised read-only

Finds operators that offer upgrades. With an origin and destination airport (IATA codes, e.g. YUL and LHR) the result is route-level: carriers with observed upgrade pricing on that airport pair (per-cabin ranges from anonymized checks, either direction), carriers confirmed by operator inventory where that upstream is enabled, and carriers whose hub or home country is at one end of the route — the last group is labelled as a hub match that is not confirmed and carries no pricing. Without a route, the result is the operator list filtered by vertical, region, and/or product.

search_upgrade_options input schema
{
  "type": "object",
  "$schema": "http://json-schema.org/draft-07/schema#",
  "properties": {
    "date": {
      "type": "string",
      "description": "Optional travel date (YYYY-MM-DD) — used for live inventory confirmation when that upstream is enabled."
    },
    "cabin": {
      "enum": [
        "BUSINESS",
        "FIRST",
        "PREMIUM_ECONOMY"
      ],
      "type": "string",
      "description": "Optional: limit observed route pricing to one target cabin."
    },
    "origin": {
      "type": "string",
      "description": "Origin airport IATA code (e.g. 'YUL'). With destination, filters to that route."
    },
    "region": {
      "enum": [
        "Americas",
        "Europe",
        "MEA",
        "APAC",
        "Cruise",
        "Rail"
      ],
      "type": "string"
    },
    "product": {
      "enum": [
        "bid_upgrade",
        "instant_upgrade",
        "seat_blocker",
        "premium_seating"
      ],
      "type": "string"
    },
    "vertical": {
      "enum": [
        "airline",
        "cruise",
        "rail",
        "hotel"
      ],
      "type": "string"
    },
    "destination": {
      "type": "string",
      "description": "Destination airport IATA code (e.g. 'LHR'). With origin, filters to that route."
    },
    "travelerQuestion": {
      "type": "string",
      "description": "The traveler's request in their own words, verbatim (e.g. 'can I upgrade my Swiss flight to business?'). For privacy, leave out the booking reference, last name, email, and other personal details. Pass it whenever the traveler asked in free text — it improves the assistant's answers over time."
    }
  },
  "additionalProperties": false
}
search_upgrade_options annotations
{
  "title": "Search Upgrade Options",
  "readOnlyHint": true,
  "openWorldHint": false,
  "idempotentHint": true,
  "destructiveHint": false
}

Prompts

Not advertised

No prompt definitions available.

Resources

13 advertised

eligibility-widget-ui://widget/eligibility.html

Advertised by the server during the last successful anonymous check.

eligibility-widget-ui://widget/eligibility.html URI
ui://widget/eligibility.html
eligibility-widget-ui://widget/eligibility-v2.html

Advertised by the server during the last successful anonymous check.

eligibility-widget-ui://widget/eligibility-v2.html URI
ui://widget/eligibility-v2.html
eligibility-widget-ui://widget/eligibility-v3.html

Advertised by the server during the last successful anonymous check.

eligibility-widget-ui://widget/eligibility-v3.html URI
ui://widget/eligibility-v3.html
eligibility-widget-ui://widget/eligibility-v4.html

Advertised by the server during the last successful anonymous check.

eligibility-widget-ui://widget/eligibility-v4.html URI
ui://widget/eligibility-v4.html
eligibility-widget-ui://widget/eligibility-v5.html

Advertised by the server during the last successful anonymous check.

eligibility-widget-ui://widget/eligibility-v5.html URI
ui://widget/eligibility-v5.html
eligibility-widget-ui://widget/eligibility-v6.html

Advertised by the server during the last successful anonymous check.

eligibility-widget-ui://widget/eligibility-v6.html URI
ui://widget/eligibility-v6.html
eligibility-widget-ui://widget/eligibility-v7.html

Advertised by the server during the last successful anonymous check.

eligibility-widget-ui://widget/eligibility-v7.html URI
ui://widget/eligibility-v7.html
watch-widget-ui://widget/watch.html

Advertised by the server during the last successful anonymous check.

watch-widget-ui://widget/watch.html URI
ui://widget/watch.html
watch-widget-ui://widget/watch-v2.html

Advertised by the server during the last successful anonymous check.

watch-widget-ui://widget/watch-v2.html URI
ui://widget/watch-v2.html
watch-widget-ui://widget/watch-v3.html

Advertised by the server during the last successful anonymous check.

watch-widget-ui://widget/watch-v3.html URI
ui://widget/watch-v3.html
watch-widget-ui://widget/watch-v4.html

Advertised by the server during the last successful anonymous check.

watch-widget-ui://widget/watch-v4.html URI
ui://widget/watch-v4.html
manage-widget-ui://widget/manage.html

Advertised by the server during the last successful anonymous check.

manage-widget-ui://widget/manage.html URI
ui://widget/manage.html
manage-widget-ui://widget/manage-v1.html

Advertised by the server during the last successful anonymous check.

manage-widget-ui://widget/manage-v1.html URI
ui://widget/manage-v1.html

90-day uptime

A lightweight connection check about every six hours, sampled on hosts with many listings. It shows the server answered, not that its tools work.

Too few checks for a percentage yet (1 of 1 answered).

  1. 2026-11-07: 1 of 1 checks answered

30-day availability

Aggregated from read-only remote checks; this is not a tool-execution or security guarantee.

Successful checks
1 of 1 (100%)
Average latency
1006 ms
95th percentile latency
1006 ms

Maintenance history

Public check and source-refresh events. Editorial and ownership records remain private.

  • · probe · passed · 1006 ms · metadata changed · 21 tool(s), 13 resource(s), 0 resource template(s)

Connect from your client

Each snippet registers the same endpoint; pick the client you use.

This server is operated by the named third party. Listing and endpoint checks are not an endorsement or a security audit. Review the operator's permissions, terms, and data handling before connecting. How listings are checked and corrected.

Claude Code

Run this once in a terminal. It registers the remote server. Use --scope project to write .mcp.json for the repo.
Claude Code configuration
claude mcp add --transport http upgrade-agent-mcp https://www.upgradeagent.ai/api/mcp

Codex

Run this once. Codex stores MCP servers in ~/.codex/config.toml (or .codex/config.toml in a trusted project).
Codex configuration
codex mcp add upgrade-agent-mcp --url https://www.upgradeagent.ai/api/mcp

Cursor

Merge this server into .cursor/mcp.json in your project, then enable upgrade-agent-mcp in your MCP settings.
Cursor configuration
{
  "mcpServers": {
    "upgrade-agent-mcp": {
      "url": "https://www.upgradeagent.ai/api/mcp"
    }
  }
}

Cline

Merge this into cline_mcp_settings.json (Cline → MCP Servers → Configure).
Cline configuration
{
  "mcpServers": {
    "upgrade-agent-mcp": {
      "type": "streamableHttp",
      "url": "https://www.upgradeagent.ai/api/mcp",
      "disabled": false
    }
  }
}

VS Code

Merge this server into .vscode/mcp.json. Use MCP: List Servers to start upgrade-agent-mcp and inspect its tools.
VS Code configuration
{
  "servers": {
    "upgrade-agent-mcp": {
      "type": "http",
      "url": "https://www.upgradeagent.ai/api/mcp"
    }
  }
}

Gemini CLI

Run this once. It writes .gemini/settings.json in the current project; pass --scope user for ~/.gemini/settings.json.
Gemini CLI configuration
gemini mcp add --transport http upgrade-agent-mcp https://www.upgradeagent.ai/api/mcp

Claude Desktop

Open Claude Settings > Connectors > Add custom connector, enter this server URL and enable it for the conversation. This is a manual remote-connector handoff, not a desktop JSON configuration.
Claude Desktop configuration
https://www.upgradeagent.ai/api/mcp

Windsurf

Merge this into ~/.codeium/windsurf/mcp_config.json, then refresh MCP in Cascade. Windsurf remote servers use serverUrl, not url.
Windsurf configuration
{
  "mcpServers": {
    "upgrade-agent-mcp": {
      "serverUrl": "https://www.upgradeagent.ai/api/mcp"
    }
  }
}

Let your agent find its tools

Find servers like Upgrade Agent MCP from your agent. Add Koskamo once to search the index for endpoints, access requirements, and client setup. Public discovery needs no key.

Do you run Upgrade Agent MCP?

Prove ownership with a DNS record, a well-known file, or your Official MCP Registry entry, and your edits publish immediately. Proofs are re-checked weekly; admins can still hide or remove a listing.

Claim this listing