Skip to main content
Glama

cineplex-mcp

An MCP (Model Context Protocol) server that lets Claude look up Cineplex Canada showtimes and find ones with good seats available — e.g. "Find showtimes for The Odyssey in IMAX 70mm near me with good seats, not the first 3 rows, not on the sides."

This is a personal-use tool, not a commercial product. Cineplex has no official partner API for this data; this server calls Cineplex's undocumented public web endpoints directly. It's built to cache aggressively, keep request volume low, and fail gracefully rather than pretend otherwise: calls are throttled rather than fired in bursts, transient failures (429/5xx, dropped sockets) are retried with backoff that honours Retry-After, and anything still broken surfaces as a clear message instead of a crash.

Demo

https://github.com/user-attachments/assets/8b19e98a-921c-4041-920b-d82a6b0f14db

This is a personal-use tool, not a commercial product. ...

Related MCP server: codex-cli-mcp-tool

Status: all five Cineplex data endpoints are confirmed working

All five calls this server depends on hit real, live apis.cineplex.com endpoints, tested end-to-end against real responses — the original four as of 2026-07-19, the full theatre directory as of 2026-07-31. See CAPTURE.md for how they were found and what to do if Cineplex changes something in the future (e.g. rotates the theatrical API's subscription key).

Setup

npm install

Node.js 18+ is required (for built-in fetch).

No environment variables or session tokens are required — every endpoint this server calls was confirmed to work unauthenticated (theatre/movie/ showtime discovery uses a static, public subscription key baked into cineplexClient.js; seat data needs no key at all).

If Cineplex rotates the subscription key

That key is public — Cineplex ships it to every visitor's browser — but it will eventually be rotated, at which point theatre/movie/showtime lookups start failing with a 401. The server resolves it from three sources, in order:

  1. CINEPLEX_SUBSCRIPTION_KEY (env var) — an explicit override. If set, it always wins and automatic discovery is skipped entirely.

  2. A key discovered automatically. On a 401, the server re-captures the key the same way a human would (per CAPTURE.md): it reads cineplex.com's homepage, walks the _next/static/chunks/*.js it references, and extracts the key sitting next to the theatrical API's URL, then retries the request with it. This runs only after a rejected key, at most once per process, so normal operation costs nothing extra.

  3. The bundled fallback in cineplexClient.js — verified current as of 2026-07-30.

If automatic re-capture also fails, the error tells you so explicitly and points at CAPTURE.md; recovery is then setting the env var, with no code change or redeploy.

The extractor anchors on the theatrical API's URL rather than on the Ocp-Apim-Subscription-Key header name, because Cineplex's bundle ships several different subscription keys (a separate one guards their marketing API, and it appears earlier in the bundle). Matching the header name alone would return that decoy — a key that 401s forever while looking like a successful re-capture.

Running

npm start

This starts the MCP server on stdio, for use by an MCP client (Claude Desktop, Claude Code, etc.) — it's not meant to be run standalone for interactive use.

Claude Desktop configuration

Add to your Claude Desktop config (claude_desktop_config.json):

{
  "mcpServers": {
    "cineplex": {
      "command": "node",
      "args": ["/absolute/path/to/cineplex-mcp/src/index.js"]
    }
  }
}

Restart Claude Desktop after editing the config.

If you ever need to override the subscription key (see above), add an env block — otherwise leave it out:

"cineplex": {
  "command": "node",
  "args": ["/absolute/path/to/cineplex-mcp/src/index.js"],
  "env": { "CINEPLEX_SUBSCRIPTION_KEY": "…" }
}

Claude Code configuration

claude mcp add cineplex -- node /absolute/path/to/cineplex-mcp/src/index.js

With an optional key override:

claude mcp add cineplex -e CINEPLEX_SUBSCRIPTION_KEY=… -- node /absolute/path/to/cineplex-mcp/src/index.js

Running in Docker

The server talks over stdio, so it works fine as a container that an MCP client docker runs per session — no port mapping needed.

Build the image:

docker build -t cineplex-mcp .

Claude Desktop config, using the image instead of a local node install:

{
  "mcpServers": {
    "cineplex": {
      "command": "docker",
      "args": ["run", "-i", "--rm", "cineplex-mcp"]
    }
  }
}

Claude Code:

claude mcp add cineplex -- docker run -i --rm cineplex-mcp

With the subscription key override, pass it through with -e:

claude mcp add cineplex -- docker run -i --rm -e CINEPLEX_SUBSCRIPTION_KEY=… cineplex-mcp

Rebuild the image (docker build -t cineplex-mcp .) after pulling changes to src/ — the client just launches whatever image tag is on disk, so a stale image silently keeps running old code.

Tools exposed

  • find_theatres{ location?, lat?, lon?, rangeKm? } → nearby theatres (id, name, address, distance), nearest first, plus a resolvedLocation block saying how the location was understood.

    Send lat/lon when you can place the location yourself — that is the primary path. Send location for the things that need looking up: a postal code ("M5B 2H1", or a bare FSA like "M5B"), a Cineplex theatre name ("Yonge-Dundas"), or a city that has a Cineplex theatre. See Location input for how the two divide the work.

  • find_movie{ title } → best fuzzy match against Cineplex's full current movie catalog, including the Cineplex movie ID. Cineplex's movies endpoint returns the whole catalog in one response (it reports a totalCount matching the items it returns), so no pagination is involved.

  • find_optimal_showtimes{ movieTitle, theatreId, date, formatMatch?, excludeFrontRows?, excludeSideSeats?, minContiguous? } → showtimes matching a format (default "IMAX", case-insensitive substring match — also works for "IMAX 70mm", "UltraAVX", "Dolby", etc.), scored for seat quality. Returns both the full scored list and an optimal subset.

  • get_optimal_seats{ theatreId, showtimeId, excludeFrontRows?, excludeSideSeats?, minContiguous? } → seat score for a single already-known showtime. Cineplex's seat endpoints are keyed by the (theatreId, showtimeId) pair, not showtimeId alone.

  • render_seat_map_asciithe default seat-map visualization. { theatreId, showtimeId, partySize?, excludeFrontRows?, excludeSideSeats?, monochrome?, theatreName?, showLabel?, buyUrl? } → a compact ASCII/emoji seat-map diagram as plain text: a centered SCREEN banner, the auditorium as a grid of squares (🟩 open, ⬛ taken, 🟪 accessible), the best partySize-block highlighted (🟦, centered within the run), a one-line recommendation, and a 🎟 Buy tickets link. Works in any MCP client with no extra setup — it's just text. Because most clients keep tool results collapsed behind a "tools used" disclosure, the diagram is only visible if the assistant pastes it into its reply, so the result ships as two blocks: a display instruction, then a ready-to-paste payload fenced by ===== COPY EVERYTHING BELOW THIS LINE ===== markers. The payload arrives pre-formatted — the grid already inside a fence, the buy line already lifted **out** of the fence as a clickable Markdown link (links don't linkify inside) — so displaying it is copy-paste, not reassembly. Pass buyUrl through from find_optimal_showtimes for the correct D-BOX-aware link, or omit it to build a cineplex.com/ticketing/preview link from the IDs. Set monochrome: true (·//+/) where emoji width misaligns the grid. Rendering logic lives in src/seatMapAscii.js.

  • render_seat_map_html — the opt-in interactive alternative; needs the bundled skill (see below). { movieTitle, theatreId, date, theatreName?, theatreAddress?, distanceKm?, formatMatch?, excludeFrontRows?, excludeSideSeats?, minContiguous? } → a complete, self-contained HTML page visualizing real seat availability: showtime chips, a pannable/zoomable auditorium seat map, live filter controls, and a stats strip. Meant to be rendered inline in the chat as a widget (via the Visualizer's show_widget), not saved to a file, published as a hosted artifact, or read as data — see src/seatMapTemplate.html/.js. The tool only injects real data into an already-built, already-tested template; it never generates new HTML/JS per call, so there's no risk of a fresh generation shipping a UI bug.

theatreId/showtimeId accept either a string or a number — Cineplex's IDs are numeric, and find_theatres/find_optimal_showtimes hand them back as numbers, so chaining one tool's output straight into the next one's input just works.

Location input

Cineplex's theatre search is coordinate-based. find_theatres takes either coordinates or a location string, and the two are meant to split the work rather than compete:

Send lat/lon for anywhere you can already place — cities, neighbourhoods, landmarks, street addresses. A language model converts those accurately and knows when it can't, so a lookup table would only duplicate it. This is the expected path and the most precise one.

Send location for what world knowledge gets wrong:

Input

Example

Resolved from

postal code / FSA

"M5B 2H1", "M5B"

bundled FSA table

Cineplex theatre name

"Yonge-Dundas", "Courtney Park"

live theatre directory

city with a theatre

"Mississauga", "London, ON"

live theatre directory

coordinates as a string

"43.65, -79.38"

parsed, not looked up

A postal code is also picked up from inside a longer string, so "123 Front St W, Toronto, ON M5J 2M2" resolves by its postal code. Input is case-, punctuation-, and accent-insensitive; a trailing country is ignored ("Halifax, NS, Canada"); provinces work as a code or a full name.

Anything else returns found: false inviting you to pass coordinates. That is the design, not a gap.

Why postal codes specifically

They are the one input neither a model nor an open geocoder handles reliably.

Canada Post's postal file is proprietary, so OSM's coverage is thin: measured against Nominatim on 2026-07-31, four of six sampled postal codes returned no match, and V6B 1A1 — downtown Vancouver — resolved to 48.87, -119.73, about 400 km away near the Washington border.

Recall fares better but fails unpredictably. Claude's own from-memory coordinates for 16 FSAs landed 12 within 10 km — Waterloo 0.1 km, Victoria 0.3 km — but placed T9K in Cold Lake when it is Fort McMurray, 264 km off, stated exactly as confidently as the correct answers. A wrong coordinate doesn't fail loudly; it returns a tidy list of theatres in the wrong city.

The bundled GeoNames table (src/data/postalCodes.json, 41 KB, CC BY 4.0) covers all 1652 FSAs. Rebuild it with npm run build:locations.

Precision

Every result reports how sharp it is:

  • exact — coordinates, or a specific theatre.

  • fsa — an urban postal area, a few blocks across.

  • city — the centroid of that city's Cineplex theatres. Fine for a small city, loose for a big one: "Toronto" lands near Don Mills, because the suburban locations outvote the downtown ones, and returns Don Mills as the nearest theatre where coordinates for downtown return Yonge-Dundas. Prefer lat/lon for large cities.

  • region — a rural FSA (a 0 in the second position, Canada Post's own convention). These span hundreds of kilometres; X0A covers the eastern Arctic and sits ~1800 km from Iqaluit. Labelled rather than passed off as a point.

Search radius

rangeKm (default 50) is enforced by this server, not by Cineplex. theatres/playingnearby accepts an accuracyKm parameter and ignores it, always returning its 15 nearest theatres: from Moose Jaw, SK a 1 km and a 200 km request come back identical, the farthest theatre 599.7 km away. Results are filtered by their reported distance so the radius means what it says. When nothing is in range, the response names the nearest theatre and its distance, so you know what to widen to.

Seat-quality parameters

  • excludeFrontRows (default 3): drop this many front rows entirely.

  • excludeSideSeats (default 3): trim this many seats from each side of every remaining row (by position, not raw seat number, so aisle gaps don't cause off-by-N errors).

  • minContiguous (default 1): require a contiguous block of at least this many available seats — set to 2 for a couple, 4 for a group, etc.

Two things the scorer does on your behalf:

  • Seats are reported by their printed label (A21, GW4) — the number actually on the ticket. Cineplex's seat columns run opposite to its seat numbers (column 3 is seat A26), so the grid position is used for adjacency but never shown as a seat number.

  • Free wheelchair and companion seating is never recommended. Those spaces are usually empty and sit dead centre, so counting them as available made them the "best block" for every party that doesn't need them. They still appear on the rendered map (marked accessible) — they're just excluded from recommendations.

Visualization: ASCII by default, interactive widget optional

There are two ways to see a seat map, and you get the first one for free.

Default: the ASCII seat map (no setup)

Out of the box, seat maps render as text via render_seat_map_ascii — a grid of emoji squares with your recommended block highlighted, printed straight into the chat:

Cineplex Yonge-Dundas · The Odyssey · 7:00 PM IMAX
Recommended: row H, seats 8–9 (2 together, center)

      SCREEN
A  🟩🟩⬛⬛⬛🟩🟩🟩🟩🟩🟩🟩
B  🟩🟩🟩🟩🟩⬛🟩🟩🟩🟩🟩🟩
C  🟩⬛⬛🟩🟩🟩🟩🟩🟩🟩🟩🟩
D  🟩🟩🟩🟩🟩🟩🟩🟩⬛🟩🟩🟩
E  🟩🟩🟩🟩⬛🟩🟩🟩🟩🟩🟩🟩
F  🟩🟩🟩⬛⬛🟩🟩🟩🟩🟩🟩🟩
G  🟩🟩🟩🟩🟩🟩🟩🟩🟩🟩⬛🟩
H  🟩🟩⬛⬛🟩🟩🟩🟦🟦🟩🟩🟩

🟩 open   ⬛ taken   🟦 your seats   🟪 accessible

(…plus a 🎟 Buy tickets: … link below the diagram.)

This needs nothing beyond the MCP server itself. It works in Claude Code, a plain terminal, or any MCP client, because the output is just text.

Optional: the interactive widget (install the bundled skill)

For a richer view, this repo also ships a Claude skill at .claude/skills/cineplex-seat-map. When you ask to see the seat map, it renders render_seat_map_html inline in the chat as a live widget — a pannable/zoomable auditorium where you can switch between theatres and showtimes, drag the front-row / side-seat / seats-together filters and watch the best block move in real time, and read a live stats strip.

The skill is opt-in per request, not a global mode. It fires on "show me the seat map", "can I see the seats", "make that interactive" — and stays out of the way for ordinary ticketing questions like "which showtime should we book?", which are answered in text. That distinction is deliberate: an earlier version triggered whenever a visual "would help", which meant every Cineplex question returned a widget instead of an answer. A decision question deserves a recommendation; the widget is a better way to look, not a substitute for answering.

To install it, copy the skill folder into wherever your client loads skills from (e.g. your user-level ~/.claude/skills/), or just open this repo as your project so .claude/skills/ is picked up automatically. Removing it leaves you with the ASCII map only.

The widget requires a client that can render inline HTML widgets (the Visualizer's show_widget). In a client without one, stay on the ASCII map — render_seat_map_html would return raw HTML with nothing to display it.

To see the widget outside a chat client (e.g. while editing its UI), run npm run preview — it writes a standalone preview.html you can open in any browser, built from a cached fixture (fetched live once, then reused offline; npm run preview:watch rebuilds on save). npm run build:shell recompiles dist/seatmap-shell.min.js after any change to src/seatMapTemplate.html; see the bump procedure documented on SHELL_VERSION in src/seatMapTemplate.js.

How the two layers relate

The MCP server works on its own. All six tools return real data as plain text/JSON — theatre lists, showtimes, seat scores, ASCII maps. You can ask "which IMAX showtimes have good seats" and get a complete answer with no skill involved. render_seat_map_html likewise just returns a finished HTML string; a client is free to save it, open it, or ignore it.

The skill is only the delivery layer for that HTML. It can't function without this server (it orchestrates these exact tools), but the server never depends on the skill — which is why they live in one repo but stay cleanly separable. In short: the server answers the question, the ASCII map draws it by default, and the skill upgrades that picture to an interactive one.

Example prompts

  • "Find Cineplex theatres in Toronto." → Claude supplies the coordinates.

  • "What's playing near M5B 2H1?" → resolved from the bundled postal table.

  • "Find theatres within 10km of 123 Front St W, Toronto."

  • "Find theatres near me at lat 43.65, lon -79.38."

  • "Look up the movie 'The Odyssey' on Cineplex."

  • "Find IMAX 70mm showtimes for The Odyssey at theatre 9806 on 2026-07-20 with good seats, not the first 3 rows or within 3 seats of the wall."

  • "Same as above but I need 2 seats together for me and my partner."

  • "Show me the seat map for that 7pm showtime." → the ASCII diagram by default; the interactive widget instead if you've installed the skill.

Testing

Unit tests (no network required)

npm test

Runs the whole test/ directory with Node's built-in test runner:

  • test/seatScoring.test.js — scoring against a synthetic 10-row, 12-seat auditorium: front-row exclusion, side-seat exclusion with row gaps, contiguous-run detection, and the minContiguous parameter.

  • test/seatMapAscii.test.js — ASCII rendering: open/taken/accessible glyph selection, the centered partySize highlight, monochrome mode, the "no block fits" message, the trailing buy-link line, and empty-layout handling.

  • test/cineplexClient.test.js — cache expiry and bounded eviction, the retry policy (which statuses are retried, Retry-After handling, the retry loop itself), client-side rangeKm enforcement, and automatic subscription-key re-capture — all driven through a stubbed fetch, so it stays offline.

  • test/locationResolver.test.js — the location cascade against the real bundled FSA table: coordinate parsing, postal codes (including the ones open geocoders and recall both get wrong), theatre-name matching, city lookup via the theatre directory, urban-vs-rural precision labelling, and the guarantee that an unresolvable string is reported rather than guessed at.

  • test/shellBuild.test.js — that the committed dist/ widget shell still matches src/seatMapTemplate.html, and that a shell change can't ship under an already-published SHELL_VERSION. See RELEASING.md.

  • test/cineplexAdapters.test.js — the code that reads Cineplex's raw JSON, run against real captured responses in test/fixtures/: seat-map normalization, showtime flattening and buy-link construction, fuzzy title matching, and a compactRows ↔ widget inflate() round trip. This is the layer that breaks when Cineplex changes shape, so the fixtures keep real field names and real value vocabularies.

All suites are pure and offline — no network access required. They run in CI on every push and pull request (.github/workflows/test.yml) against Node 18, 20, and 22.

Live smoke test

npm run smoke

Unlike npm test, this makes real requests to Cineplex. It chains all five endpoints the way the MCP tools do — theatre directory → location resolution → theatres → movies → showtimes → seat layout + availability → score — and exits non-zero if any step fails:

  ok   theatre directory: 152 theatres, 152 with coordinates
  ok   location: "Toronto" -> 43.6706, -79.3918 (cineplex-city, city)
  ok   theatres in range: 15 within 25km — nearest is Cineplex Cinemas Yonge-Dundas and VIP (7130)
  ok   movies: 250 in catalog
  ok   fuzzy match: "Spider-Man: Brand New Day" -> id 37997 (score 1000)
  ok   showtimes: 95 at Cineplex Cinemas Yonge-Dundas and VIP on 2026-07-31 — sampling 2026-07-31T19:10:00 (UltraAVX 3D D-BOX Dolby Atmos)
  ok   seat map: 15 rows, 387 seats
  ok   scoring: 49 available (0 in the preferred zone), best block none

All endpoints healthy.

A failure here almost always means something changed upstream — see CAPTURE.md's "If this breaks in the future" section, which maps each symptom to its fix. This is deliberately not part of CI: pointing scheduled traffic at an undocumented API would be rude, and an upstream outage shouldn't redden the build on unrelated commits.

Architecture

src/
  index.js              # MCP server entrypoint; registers tools, thin glue only
  cineplexClient.js     # All HTTP calls to Cineplex's API; caching + throttling
  locationResolver.js   # Postal code / theatre name / city -> lat/lon, for
                        # the cases a caller can't resolve itself. Pure and
                        # offline; no geocoding service. Deliberately narrow —
                        # see "Location input" in the README.
  data/
    postalCodes.json    # Generated: GeoNames FSA centroids (CC BY 4.0).
                        # Rebuild with npm run build:locations.
  seatScoring.js        # Pure functions: normalized seat map -> score. No
                        # network calls, no Cineplex-specific knowledge.
  seatMapAscii.js       # Default visualization: renders raw seat data as the
                        # ASCII/emoji text diagram. Pure, network-free.
  seatMapTemplate.html  # Optional interactive widget UI (CSS + JS): tabs,
                        # showtime chips, pan/zoom seat map, live filters.
                        # Has a JSON-data placeholder, no server logic.
  seatMapTemplate.js    # Loads the .html above and injects real data into it.
                        # Never regenerates the HTML. Also builds the small
                        # widget wrapper that points at the CDN-hosted shell.
test/
  seatScoring.test.js     # Offline unit tests: scoring, ASCII rendering, the
  seatMapAscii.test.js    # client's cache/retry/key-recapture policy, and the
  cineplexClient.test.js  # shell build guards (npm test runs the whole
  shellBuild.test.js      # directory; no network access needed).
scripts/
  smoke.mjs             # Live end-to-end check of all five Cineplex
                        # endpoints (npm run smoke). Not run in CI.
  build-location-data.mjs # Regenerates src/data/postalCodes.json from GeoNames
                        # (npm run build:locations). Documents why the tables
                        # are bundled instead of geocoded at request time.
  build-shell.mjs       # Compiles seatMapTemplate.html into dist/ (npm run
                        # build:shell) so the widget's static CSS/JS can be
                        # served from a CDN instead of re-emitted per request.
  preview-seatmap.mjs   # Local widget preview harness (npm run preview).
.github/
  workflows/test.yml    # Runs npm test on push/PR against Node 18, 20, 22.
dist/
  seatmap-shell.min.js  # Built output of build-shell.mjs; committed so a
  shell-manifest.json   # tagged commit is fetchable via jsDelivr. The
                        # manifest records which SHELL_VERSION the committed
                        # shell belongs to, so a missed bump gets caught.
.claude/
  skills/
    cineplex-seat-map/  # Optional visualization skill: renders
      SKILL.md          # render_seat_map_html's output inline as a widget.
                        # Consumes the server; the server never depends on it.
CAPTURE.md              # Record of how the live endpoints were found, and how
                        # to re-capture them if something changes
RELEASING.md            # Tag scheme (server `v1.0.0` vs widget `widget-vN`)
                        # and the release checklist for each
docs/
  PRD-original.md       # The original build spec. Historical record only —
                        # describes the project as planned, not as built.

seatScoring.js never sees Cineplex's raw JSON shape — only the normalized form. normalizeCineplexSeatMap() in cineplexClient.js is the sole adapter between the two, so a future Cineplex response-shape change (or a future non-Cineplex chain) only requires a new adapter, not scoring changes.

Non-goals (v1)

  • No ticket purchasing — read-only lookups only. Pricing itself isn't even fetched; Cineplex doesn't expose it outside its login-gated checkout flow.

  • No chains other than Cineplex.

  • No persistent database — in-memory cache only. Theatres, movies, and seat layouts are cached for 24h, bounded at 200 entries with expired-then- oldest-first eviction so a long-running server can't grow without limit. Seat availability is never cached, since it changes as people book and abandon carts.

  • No login/auth flows. Every endpoint this server calls was confirmed to work without one.

License

MIT — see LICENSE. This remains an unofficial, personal-use tool built against Cineplex's undocumented endpoints; see the disclaimer at the top of this file before relying on it for anything beyond that.

src/data/postalCodes.json is derived from the GeoNames postal-code dataset, used under CC BY 4.0.

Project history

docs/PRD-original.md is the original build spec, kept as a historical record — it holds the background research (why Fandango was ruled out, the Open Theatre Seats fallback) and the reasoning behind the non-goals. It describes the project as planned, not as built, and is marked accordingly; this README is the current documentation.

Available Tools

5 tools
find_movieFind a Cineplex movie by titleA

Fuzzy-match a movie title against Cineplex's current catalog (pages through all results) and return the best match, including the Cineplex movie ID needed by other tools.

ParametersJSON Schema
NameRequiredDescriptionDefault
titleYesMovie title to search for, e.g. 'The Odyssey'

TDQS

A4/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries full burden. It discloses fuzzy matching and paging through all results, but does not explicitly state that it is a read-only operation or discuss potential performance impacts. More transparency about safety (non-destructive) would improve the score.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single, well-structured sentence that front-loads the primary action. No extraneous information; every part is meaningful and earns its place.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given the simple parameter set (one required) and no output schema, the description covers the essential behavior, including the fuzzy matching and page-through mechanism, and explains the tool's relevance to the workflow. It could be slightly more explicit about return format, but this is a minor gap.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

With 100% schema description coverage, the description adds value by explaining that the title is fuzzy-matched and that the result is the best match, which is not evident from the schema alone. This provides context beyond the parameter's type and description.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's action: fuzzy-match a movie title against Cineplex's current catalog. It specifies the resource (movie titles, Cineplex catalog) and output (best match with movie ID). It distinguishes from sibling tools like find_theatres.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies that the tool is a preliminary step to obtain a movie ID for other tools, but it does not explicitly state when to use it versus alternatives or when not to use it. No direct usage guidelines beyond inferred context.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_optimal_showtimesFind optimal Cineplex showtimesA

Given a movie title, theatre, and date, find showtimes matching a format (default IMAX) and check which ones have good seats available (not front rows, not sides, with a contiguous block big enough for your group).

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesDate in YYYY-MM-DD format
theatreIdYesCineplex theatre ID, from find_theatres
movieTitleYesMovie title, e.g. 'The Odyssey'
formatMatchNoCase-insensitive substring to match against the showtime's format/experience tag, default 'IMAX'
minContiguousNoMinimum contiguous open seats required, default 1
excludeFrontRowsNoNumber of front rows to exclude, default 3
excludeSideSeatsNoNumber of seats to exclude from each side wall, default 3

TDQS

A3.7/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

With no annotations, the description takes on the full burden. It transparently discloses key behaviors: seat quality filters (exclude front rows, side seats, require contiguous block) and default values for format, front rows, side seats, and contiguous seats. This goes beyond basic purpose.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single sentence of 35 words, front-loading the core action. It is efficient and avoids fluff, though it could be slightly more concise by splitting into two sentences.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness2/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

No output schema is provided, and the description does not clarify the return format (e.g., list of showtimes with seat availability markers). For a tool with 7 parameters and complex logic, this omission leaves the agent uncertain about what to expect. Some return details are essential for correct usage.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the schema already documents all parameters. The description summarizes the seat logic but adds only modest extra context (e.g., 'good seats' definition). It does not introduce new parameter meanings beyond what the schema provides. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's action: given a movie, theatre, and date, find showtimes matching a format and check for good seats. It uses specific verbs ('find', 'check') and resources ('showtimes', 'seats'). The purpose is unambiguous and distinguishes it from sibling tools like find_theatres and find_movie.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines3/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description implies usage context (when you have movie, theatre, date) but does not explicitly compare with sibling tools like get_optimal_seats or render_seat_map_html. No when-not-to-use advice or alternative recommendations are provided.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

find_theatresFind Cineplex theatresB

Find Cineplex theatres near a location (by lat/lon and search radius). Returns id, name, address, and distance for each theatre.

ParametersJSON Schema
NameRequiredDescriptionDefault
latYesLatitude of the search origin
lonYesLongitude of the search origin
rangeKmNoSearch radius in kilometers (default 50)

TDQS

B3.3/5.0
Behavior2/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description carries full burden. It mentions return fields but omits details like sorting, pagination, or whether all theatres are returned. Basic transparency only.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

Two sentences: one for purpose and inputs, one for outputs. No wasted words, highly efficient.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

For a simple 3-parameter query tool with no output schema, the description adequately explains inputs and outputs. Could mention default radius or result ordering, but overall sufficient.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters4/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema provides full parameter descriptions (100% coverage). The description adds the return fields (id, name, address, distance), which is valuable context beyond the schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose4/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool finds Cineplex theatres near a location using lat/lon and radius, and lists the return fields. It does not explicitly distinguish from sibling tools like find_movie, but the purpose is specific enough.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines2/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

No guidance on when to use this tool vs alternatives like find_movie or get_optimal_seats. No mention of prerequisites or exclusions.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

get_optimal_seatsScore seats for a known showtimeA

Given a Cineplex theatre ID and showtime ID (e.g. from find_optimal_showtimes), fetch and score its seat map for good seats.

ParametersJSON Schema
NameRequiredDescriptionDefault
theatreIdYesCineplex theatre ID
showtimeIdYesCineplex showtime ID
minContiguousNoMinimum contiguous open seats required, default 1
excludeFrontRowsNoNumber of front rows to exclude, default 3
excludeSideSeatsNoNumber of seats to exclude from each side wall, default 3

TDQS

A3.9/5.0
Behavior3/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations are provided, so the description carries the full burden. It says 'fetch and score' which implies a read operation, but does not disclose details like authentication requirements, rate limits, or scoring algorithm. Moderate transparency.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness5/5

Is the description appropriately sized, front-loaded, and free of redundancy?

A single, well-structured sentence that is front-loaded with the essential information. No wasted words.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness3/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

The tool has 5 parameters but no output schema. The description does not explain the return value (e.g., seat scoring details). While the context signals and sibling tools provide some background, the description itself could be more complete for a tool with moderate complexity.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so the input schema already describes each parameter's purpose. The description adds minimal extra meaning beyond stating that theatreId and showtimeId are from find_optimal_showtimes. Baseline 3 is appropriate.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool's function: given a theatre ID and showtime ID, it fetches and scores seat maps. It also references the sibling tool find_optimal_showtimes, which distinguishes it from other tools like render_seat_map_html.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines4/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

The description explicitly mentions that theatreId and showtimeId can come from find_optimal_showtimes, guiding the agent to use this tool after finding showtimes. It does not explicitly state when not to use it, but the context is clear.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

render_seat_map_htmlRender an interactive seat map widgetA

Given a movie title, theatre, and date, returns a complete, self-contained, already-tested HTML page that visualizes real seat availability: theatre header, a showtime picker, a pannable/zoomable auditorium seat map, live front-row/side/min-together filter controls, and a stats strip. IMPORTANT: render the returned HTML inline in the chat as a widget (via the Visualizer's show_widget / widget_code) exactly as given — never save it to a file, publish it as a hosted artifact, or open it in a browser. Do not rewrite, regenerate, paraphrase, or modify the code in any way, just pass it through verbatim. Pass theatreName/theatreAddress/distanceKm through from a prior find_theatres result if you have them, to avoid an extra lookup.

ParametersJSON Schema
NameRequiredDescriptionDefault
dateYesDate in YYYY-MM-DD format
theatreIdYesCineplex theatre ID, from find_theatres
distanceKmNoTheatre distance in km, e.g. from find_theatres
movieTitleYesMovie title, e.g. 'The Odyssey'
formatMatchNoCase-insensitive substring to match against the showtime's format/experience tag, default 'IMAX'
theatreNameNoTheatre display name, e.g. from find_theatres — defaults to 'Theatre {id}' if omitted
minContiguousNoMinimum contiguous open seats required in the initial view, default 1 (its no-op value)
theatreAddressNoTheatre street address, e.g. from find_theatres
excludeFrontRowsNoFront rows to exclude in the initial view, default 0 (widget opens unfiltered; the user can adjust it live)
excludeSideSeatsNoSeats to exclude from each side wall in the initial view, default 0 (widget opens unfiltered; the user can adjust it live)

TDQS

A4.3/5.0
Behavior4/5

Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?

No annotations provided, so description must disclose behavior. It explains the HTML content and constraints (inline rendering, no modification). However, it lacks details on failure modes or data freshness. Overall, it provides key behavioral context.

Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.

Conciseness4/5

Is the description appropriately sized, front-loaded, and free of redundancy?

The description is a single paragraph but front-loads the core purpose. Every sentence adds value, though it could be more structured. It is concise enough for the complexity involved.

Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.

Completeness4/5

Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?

Given 10 parameters and no output schema, the description covers output format (HTML widget), usage constraints, and parameter hints. It lacks error handling details, but overall provides a solid understanding of the tool.

Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.

Parameters3/5

Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?

Schema coverage is 100%, so description adds limited semantic value. It mentions passing theatreName/theatreAddress/distanceKm from prior results, which adds usage context, but does not elaborate on parameter meanings beyond schema.

Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.

Purpose5/5

Does the description clearly state what the tool does and how it differs from similar tools?

The description clearly states the tool returns an HTML page visualizing seat availability, specifying the inputs (movie, theatre, date) and the output (self-contained widget). It distinguishes from siblings like find_theatres or find_movie by focusing on rendering a visual widget.

Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.

Usage Guidelines5/5

Does the description explain when to use this tool, when not to, or what alternatives exist?

Explicit instructions are given: render inline via show_widget, never save to file, do not modify code. Also advises passing theatreName/theatreAddress/distanceKm from find_theatres to avoid extra lookups. This clarifies when and how to use the tool.

Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.

TDQS

A4/5.0
Disambiguation5/5

Each tool targets a distinct step in the cinema experience: location search, movie lookup, seat scoring, showtime filtering, and rendering. No overlapping purposes.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern with underscores, making them predictable and clear.

Tool Count5/5

Five tools is a well-scoped set for a cinema information server; each serves a necessary function without redundancy.

Completeness4/5

Covers the main user journey from finding theatres to visualizing seat maps, but lacks a direct tool for listing movies or showtimes without seat checks, which may require tool chaining.

Maintenance

ActivityMaintained
ResponsivenessSyncing

Resources

Unclaimed servers have limited discoverability.

Looking for Admin?

If you are the server author, to access and configure the admin panel.

Related MCP Connectors

Related MCP Servers

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/yinbri/cineplex-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server