Charter Boats
Search 14,000+ charter boats with live prices, plus marinas, anchorages, routes and itineraries. Eleven read-only tools, no authentication.
Hosted MCP Server
npx add-mcp 'https://charter.boats/mcp'Installs into Claude Code, Codex, Cursor and more
Documentation
Same in API v1.0 and v1.1
The Charter Boats MCP server lets Claude, ChatGPT, Cursor, and any MCP-compatible AI assistant search boats, locations, POIs, routes, trips, and content -- with rich HTML widgets for visual boat and destination cards.
Endpoint: https://charter.boats/mcp Install / quickstart page: open https://charter.boats/mcp in a browser. Transport: Streamable HTTP (JSON-RPC 2.0). Auth: None. The server passes only the caller's IP on to the API, so an API key sent to /mcp has no effect — MCP calls are neither attributed to an account nor affiliate-tagged. See also Rate limits. Spec: MCP Apps 2026-01-26.
Deployment
The server is a Cloudflare Worker routed at charter.boats/mcp. It proxies tool calls to the Charter Boats AI API (https://charter.boats/api/ai/*) and serves two HTML widgets as MCP App resources.
AI assistant → https://charter.boats/mcp (CF Worker) → charter.boats/api/ai/*
A single /mcp URL handles three things:
GETwithAccept: text/html→ install / quickstart page (HTML)GETwithAccept: application/json→ server info JSONPOST→ MCP JSON-RPC
Tools
Eleven read-only tools. Each returns the underlying API response as structuredContent (which the widgets render) plus a short text summary for the model. A search that finds nothing still returns the API's zero-results block — no_results (searched, why, try_next) and note — in structuredContent.
Search
| Tool | Description | Widget |
|---|---|---|
search_boats | Boats by location, type, dates, capacity, budget. Returns up to 8 with prices, images, booking links. | ✓ boats |
search_locations | Marinas, harbours and anchorages three ways — see below. Up to 10, each with its photo, boat count and cheapest day rate, on a numbered map. | ✓ locations |
search_pois | Restaurants, fuel, groceries, etc. near a destination. Up to 10. | — |
search_routes | Sailing passages between destinations. Up to 5. | — |
search_trips | Multi-day curated itineraries. Up to 5. | — |
search_content | Articles, guides, FAQs (semantic search); type: "api" searches these API docs. Up to 5. | — |
search_locations answers three different questions, picked by which inputs you send:
- By name —
q(min 2 characters): "Lefkada", "Dubrovnik". - By popularity in an area —
region(a sailing region as guests say it: Dalmatia, the Ionian, the Cyclades…),country,city, optionallytype(marina,harbour,anchorage,bay,mooring,spot— the same words the results carry back,spotbeing an unclassified stop) andmonth(1-12, default the current month). Ranked bysort:popularity(default — observed vessel traffic for that month),boats(charter fleet size) orrating. - By reach from a place —
from(a location id or slug from an earlier result) pluswithin_nm(10,20,35,55or100; default 35): the places boats were recorded sailing to from there, most-travelled first, with estimated distance and hours at 6 knots.
See Search Locations for the response of each mode.
Detail
| Tool | Description |
|---|---|
get_boat_details | Full specs, 365-day availability + pricing ranges, bookable check-in/check-out slots, required/optional fees, active discounts, cancellation policy, check-in/out times. |
get_boat_standouts | What is better or worse about one boat than similar boats for a week — each pro and con with how it compares; anything unlisted is ordinary for boats like it. compare_by picks similar boats by price (default), guests or length; cutoff_pct and fallback set how much is named. See What Stands Out. |
get_poi_details | Description, opening hours, address, contact, nearby marinas, special offers. POIs carry no rating or review count. |
get_location_details | Description, amenities, contact, boat count and cheapest day rate, plus tracked-AIS insight: how busy it is month by month (against its own peak, never another place), how boats use it (share of overnight visits, typical day-stop length, what hour it fills), whether it is a hidden gem, where boats sail to from it (most-travelled first, each with its share of the tracked trips and an estimated sailing time at 6 knots), and the nearest bookable base. |
get_trip_details | Day-by-day stops, distances, activities, highlights, notes. |
Full input schemas are exposed via tools/list -- view them in MCP Inspector by connecting to https://charter.boats/mcp.
Prompt presets
The server registers three prompts surfaced as one-click starters in supporting clients:
plan-sailing-trip-- destination + optional guests/dates/budgetfind-charter-boat-- location + optional type/guests/datesexplore-destination-- single destination, surfaces marinas + POIs + routes
UI widgets
Two HTML widgets are served as MCP App resources:
| Widget | URI | Used by |
|---|---|---|
| Boats | ui://widget/boats-{hash}.html | search_boats |
| Locations | ui://widget/locations-{hash}.html | search_locations |
The {hash} is a hash of that widget's own HTML, so the URI changes if and only if the widget does. ChatGPT caches MCP resources by URI with no expiry — a fixed URI means a redeployed widget is never re-read, however many times it ships — and OpenAI's guidance is to give the template a new URI when its HTML, JS or CSS changes. Read the current values from resources/list; never hard-code one. A read of a previously published URI (including the original unhashed ui://widget/boats.html) still returns the current widget rather than an error, so a host holding a stale URI degrades to old-metadata-but-correct-markup instead of a broken card.
Both widgets:
- Use the
text/html;profile=mcp-appMIME type. - Declare their image CSP twice over:
_meta.ui.csp.resourceDomains(the MCP Apps standard, which Claude reads) and_meta["openai/widgetCSP"].resource_domains(the snake_case compatibility key, which is the only one ChatGPT reads — without it ChatGPT applies a locked-down default and every boat photo renders as a broken image)._meta.ui.prefersBorder/openai/widgetPrefersBorderand_meta.ui.resourceUri/openai/outputTemplateare paired the same way. - List exact origins, never wildcards — ChatGPT rejects a
*.example.comentry and one bad entry discards the whole list. The allowed set ischarter.boats,media.charter.boats, our storage bucket's direct origin, andwsrv.nl. Boat and location photos are served frommedia.charter.boats(listed explicitly, since a CSP host source matches that host alone andcharter.boatsdoes not cover its subdomains), and a boat photo not yet copied to our storage resizes through wsrv. The locations widget also draws a static map of its results fromcharter.boats/api/ai/map, pins numbered like the cards below it — the Mapbox token stays on our server, andsearch_poishas no widget — itsimage_urlvalues are passed through as stored (some on our storage bucket, many at a third-party site's own address: a review site, a venue's website, a local guide), and nothing renders them inside a widget. - Implement the full MCP Apps handshake:
sandbox-resource-ready→ui/initialize(withprotocolVersion,appInfo,appCapabilities) →ui/notifications/initialized→ render onui/notifications/tool-result. - Report height via
ui/notifications/size-changed, measured frombody.scrollHeight/#app(the document element returns 0 inside Claude's sandbox). - Route link clicks through
ui/open-linksince sandboxed iframes blocktarget="_blank". - Respect host theme: explicit
theme: 'dark' | 'light'fromhost-context-changedoverrides theprefers-color-schemeCSS fallback.
Install
For end users: open https://charter.boats/mcp in any browser -- the page has copy-paste install steps for Claude.ai, Claude Desktop, ChatGPT, Cursor, and MCP Inspector.
Quick reference
Claude.ai / Claude Desktop: Settings → Connectors → Add custom connector → https://charter.boats/mcp (Pro/Max/Team/Enterprise required).
ChatGPT: Settings → Apps → Create app → MCP Server → https://charter.boats/mcp. Widget rendering requires the ChatGPT Apps program; Developer mode shows tool calls as text only.
Cursor: add to ~/.cursor/mcp.json:
{
"mcpServers": {
"charter-boats": { "url": "https://charter.boats/mcp" }
}
}
MCP Inspector: npx @modelcontextprotocol/inspector → Streamable HTTP → https://charter.boats/mcp.
Rate limits
Tool calls are subject to the no-key /api/ai/* rate limit, counted on the IP that calls /mcp — the server forwards that address, so each caller is limited on its own, not pooled with every other MCP user. Claude and ChatGPT, calling from Anthropic's and OpenAI's published address ranges, are counted per platform instead of per IP (see Rate limits). It forwards no key. A limited call surfaces as a tool error (API 429) whose message links to the same search on charter.boats.
Differences from the Custom GPT
Both integrations call the same /api/ai/* endpoints but expose them differently:
| Feature | Custom GPT (Actions) | MCP Server |
|---|---|---|
| Protocol | OpenAPI 3.1 | Model Context Protocol (Streamable HTTP) |
| Rich UI | No | Yes -- boats + locations widgets |
| Transport | HTTPS | JSON-RPC over HTTP |
| Session state | GPT conversation ID | Stateless per request |
| Rate limit | Up to 30 / 10 min per OpenAI user, plus the daily per-IP limit | Per calling IP — see Rate limits |
| Hosts | ChatGPT only | Claude, ChatGPT Apps, Cursor, Continue, any MCP client |