onthecheap-mcp
Read-only MCP server for finding free and cheap things to do across 14 US "On the Cheap" city sites, plus their deals archive.
List cities —
otc_list_sitesreturns everysitekey (charlotte, denver, miami, national, …) and the area it covers.Day's events —
otc_list_eventslists a date's listings with time, price and venue;free_onlykeeps just no-cost ones.Month scan —
otc_events_month_overviewgives per-day true totals plus short previews, to spot busy days.Search articles —
otc_search_postsfilters by text, category, location and publication date range, returning slim summaries.Read an article —
otc_get_postfetches one post in full by id, slug or URL, as plain text or raw HTML.Find filters —
otc_list_categoriesandotc_list_locationsreturn per-site ids and post counts.Check connectivity —
otc_healthcheckverifies a site is reachable and reports error kinds likeedge_blockedortimeout.Good to know — no credentials or config;
siteis required every call (no default); expired deals are excluded unlessinclude_expired; category/location ids are per-site;nationalis only for non-event tools.
Provides tools to access and search event listings, articles, and categories from the On the Cheap network of WordPress-based local guides across 14 US cities.
Click on "Deploy Server".
Wait a few minutes for the server to deploy. Once ready, it will show a "Started" state.
In the chat, type
@followed by the MCP server name and your instructions, e.g., "@onthecheap-mcpWhat's free in Charlotte this weekend?"
That's it! The server will respond to your query, and you can continue using it as needed.
Here is a step-by-step guide with screenshots.
onthecheap-mcp
MCP server for the On the Cheap network — local guides to free and cheap things to do across 14 US cities. Daily event listings with times, prices and venues, plus a searchable archive of deals and guides.
Developed and maintained by AI (Claude Code). Use at your own discretion.
No credentials required. Every site is public, so the server reads them server-side over plain HTTPS. There is nothing to configure beyond which city you want, and no browser extension involved.
Install
npx onthecheap-mcpOr as a Claude Code plugin:
/plugin marketplace add chrischall/onthecheap-mcp
/plugin install onthecheap-mcpRelated MCP server: valet-parking-directory
Choosing a city
One server reads the whole network. Every tool takes a site argument
naming the city to read — there is no default and no configuration step:
Key | Site | Area |
| Charlotte On The Cheap | Charlotte, NC |
| Mile High on the Cheap | Denver, CO |
| Atlanta on the Cheap | Atlanta, GA |
| Chicago on the Cheap | Chicago, IL |
| Columbus on the Cheap | Columbus, OH |
| Greater Seattle on the Cheap | Seattle–Tacoma |
| Kansas City on the Cheap | Kansas City |
| South Florida on the Cheap | Miami / Broward / Palm Beach |
| Orlando on the Cheap | Orlando, FL |
| Portland Living on the Cheap | Portland, OR |
| RVA on the Cheap | Richmond, VA |
| Southern Maine on the Cheap | Southern Maine |
| Triangle on the Cheap | Raleigh / Durham / Chapel Hill |
| Living On The Cheap | US-wide deals (no local events calendar) |
Common aliases work too — milehigh, raleigh, rva, kc, southflorida.
otc_list_sites reports the same list.
site is required rather than defaulted on purpose: a server that quietly fell
back to one city would answer a question about Denver with Charlotte's data and
give no sign anything was wrong. An unknown key is refused with the valid ones
listed.
Tools
All tools are read-only. Every tool except otc_list_sites takes a required
site argument. The two event tools reject national, which has no local
events calendar — it is still searchable via the other tools.
Tool | What it does |
| Everything on a given day — time, price, venue. |
| Day-by-day counts for a month, to find the busiest days. Each day's list is a preview; |
| Search articles by text, category, location and date range. Returns slim summaries by default. |
| One article in full, as readable text or raw HTML. Accepts an id, slug, or URL. |
| Category ids and post counts, for filtering searches by topic. |
| Local area ids and post counts, for filtering geographically. |
| The cities in the network and their |
| Confirm one site is reachable; on failure |
Examples
What's free in Charlotte this Saturday?
Find kids' events in Lake Norman in August
Compare free things to do in Denver and Portland next weekend
Two things worth knowing
Retired deals are excluded by default. Each site parks expired offers in an
expired category, so searches skip them and you don't get deals that no
longer exist. Pass include_expired: true to search the archive. The category's
id differs on every site, so it's resolved by slug at request time — a
hardcoded id silently disables the filter elsewhere.
Category and location ids are per-site. Each site is a separate WordPress
install, so id 13 is a different category on every one of them. Resolve ids
against the same site you then search — an id borrowed from another city will
filter to something unrelated rather than error.
Month overviews are previews, with honest counts. The calendar shows at
most four listings per day. otc_events_month_overview reports each day's
true total alongside the preview — call otc_list_events with a date for the
complete schedule.
Configuration
None. The city is a per-call site argument, not an environment variable, so
there is nothing to set up before use.
Development
npm install
npm test
npm run buildSee docs/OTC-API.md for the verified data surface,
including the events calendar's US M-D-YYYY date routing (an ISO date is
silently parsed as 1970), the month-view truncation, and why term ids are never
hardcoded.
License
MIT
Available Tools
8 toolsotc_events_month_overviewOverview of a city’s events across a monthARead-onlyIdempotent
Day-by-day overview of a whole month from an "on the Cheap" city’s events calendar: for each day, the true number of listings and a short preview of them. Pass the site key for the city (see otc_list_sites). The calendar shows at most four listings per day, so events is a preview while total is the real count — call otc_list_events for a specific date to get that day's complete schedule. The national hub has no local calendar and is not a valid site here. Use this to find the busiest days or scan a month at a glance. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| site | Yes | Which "on the Cheap" city to read. Required — there is no default site. One of: charlotte, denver, atlanta, chicago, columbus, seattle, kansascity, miami, orlando, portland, richmond, southernmaine, triangle, national. Common aliases also work (milehigh, raleigh, rva, southflorida, kc, …). Use otc_list_sites for the full list with the area each one covers. | |
| month | No | Month to summarise, as ISO YYYY-MM. Defaults to the current month in the city’s own time zone. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Even with readOnlyHint/openWorldHint/idempotentHint annotations, the description adds crucial behavioral context: 'The calendar shows at most four listings per day, so events is a preview while total is the real count'. It discloses the preview limitation, the invalid national hub, and month default behavior, going well beyond the annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is front-loaded with the core purpose, and every subsequent sentence adds distinct value: preview vs. total, alternative tool, invalid site, use cases, and read-only confirmation. It is slightly longer than average but contains zero filler; every clause earns its place.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a two-parameter tool with no output schema, the description is remarkably complete: it explains the main return fields (events vs total), the four-listing cap, the month default, invalid site values, and the alternative tool for full schedules. An agent has everything needed to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value on top by telling the agent to pass the site key, referencing otc_list_sites, and explicitly stating the national hub is not valid. Month semantics are fully covered by the schema, so a modest bump to 4 is appropriate.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb+resource: 'Day-by-day overview of a whole month' and clearly states the output concept ('true number of listings and a short preview'). It distinguishes itself from siblings by naming otc_list_events (for complete daily schedules) and otc_list_sites (for city keys), so an agent knows exactly what this tool does and does not do.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives explicit when-to-use guidance: 'Use this to find the busiest days or scan a month at a glance,' and directs the agent to otc_list_events for a specific date's complete schedule. It also warns that the national hub is not a valid site, and points to otc_list_sites for key lookup — clear routing versus alternatives.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
otc_get_postGet an On the Cheap articleARead-onlyIdempotent
Fetch one "on the Cheap" article in full by numeric id, slug, or full URL. Pass the site key for the city the article belongs to — an id or slug from one site will not resolve on another, and a full URL must match the site you name. Returns the article text as readable plain text by default; set format to "html" for the original markup. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| post | Yes | Post id, slug, or full article URL | |
| site | Yes | Which "on the Cheap" city to read. Required — there is no default site. One of: charlotte, denver, atlanta, chicago, columbus, seattle, kansascity, miami, orlando, portland, richmond, southernmaine, triangle, national. Common aliases also work (milehigh, raleigh, rva, southflorida, kc, …). Use otc_list_sites for the full list with the area each one covers. | |
| format | No | Body format: readable text (default) or raw HTML |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark the tool read-only, idempotent, and open-world, and the description repeats read-only, which is redundant. However, it adds meaningful behavioral details beyond annotations: site-scoped resolution, the requirement that a URL match the named site, and the default plain-text output with optional HTML.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences with no wasted verbiage: the action comes first, then the critical site-scoping constraint, then the output format option. The word 'Read-only' is redundant with annotations but harmless and not at the cost of conciseness.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a read-only fetch operation with three parameters and no output schema, the description covers the essential call behavior: identifiers, required site, cross-site matching constraints, and the return format and its switch. Nothing critical is missing for an agent to invoke the tool correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value by explaining that ids and slugs are site-specific and will not resolve on another site, and that a full URL must match the site passed. This supplements the schema's parameter descriptions rather than repeating them.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb ('Fetch') and a precise resource ('one On the Cheap article'), and defines the accepted identifiers (numeric id, slug, or full URL). This clearly distinguishes it from sibling tools like otc_search_posts, which search rather than fetch a single article by identifier.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description gives clear operational context: a site key is required, must match the article's city, and a full URL must match the named site. It does not explicitly mention when to choose this tool over a sibling, but the contrast between fetching one known article and searching is implied strongly enough.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
otc_healthcheckCheck an On the Cheap site’s connectivityARead-onlyIdempotent
Verify one "on the Cheap" site is reachable and its public API is responding. Pass the site key for the city (see otc_list_sites). The sites need no credentials, so this checks connectivity only. On failure error.kind names what broke: edge_blocked (a CDN/WAF refused the request before it reached the site), http, timeout or transport. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| site | Yes | Which "on the Cheap" city to read. Required — there is no default site. One of: charlotte, denver, atlanta, chicago, columbus, seattle, kansascity, miami, orlando, portland, richmond, southernmaine, triangle, national. Common aliases also work (milehigh, raleigh, rva, southflorida, kc, …). Use otc_list_sites for the full list with the area each one covers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Goes well beyond annotations (readOnly/openWorld/idempotent) by enumerating failure modes via error.kind: edge_blocked (with the meaning — CDN/WAF refused pre-site), http, timeout, transport. That is exactly the operational context an agent needs to interpret a failure.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four tight sentences, front-loaded with purpose, then the required param, then the connectivity caveat, then the failure taxonomy. No filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-param read-only probe with no output schema, the definition covers purpose, required input, credential-free nature, and the full error taxonomy an agent needs to act on results. Nothing material is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100% and already lists the enum values, aliases, and the otc_list_sites pointer. Description only repeats the sibling pointer already in the schema, adding no new param detail beyond baseline.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
Specific verb+resource: verifies a named site is reachable and its public API responds. Distinct from all siblings (list/get/search tools) — none of which perform a connectivity probe.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
States it needs a `site` key and points to otc_list_sites for valid values and coverage. Clarifies this is connectivity-only since no credentials are needed, implicitly contrasting with any authenticated operations. No explicit 'when not to use' beyond that.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
otc_list_categoriesList a city’s article categoriesARead-onlyIdempotent
List one "on the Cheap" site's article categories with their ids and post counts (kids, music, food, festivals, art, museums, and so on). Pass the site key for the city (see otc_list_sites). Use an id to filter otc_search_posts by topic — ids are per-site, so use them only against the site they came from. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| site | Yes | Which "on the Cheap" city to read. Required — there is no default site. One of: charlotte, denver, atlanta, chicago, columbus, seattle, kansascity, miami, orlando, portland, richmond, southernmaine, triangle, national. Common aliases also work (milehigh, raleigh, rva, southflorida, kc, …). Use otc_list_sites for the full list with the area each one covers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already mark this read-only, idempotent, and open-world, so the safety profile is covered. The description adds meaningful behavioral context: category ids are per-site and must only be used against the originating site, and results include post counts.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three short sentences front-load the result and then give parameter and cross-tool guidance. The final 'Read-only.' is redundant with the readOnlyHint annotation, so it does not fully earn its place, but the overall size is appropriate.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With one fully documented parameter and no output schema, the description supplies the key return fields ('ids and post counts') and the cross-tool relationships needed to use the result correctly. It does not specify the exact response shape or pagination, but for a simple read-only list this is not a serious gap.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema description coverage is 100%, and the site property is fully documented with valid values and aliases, so the baseline applies. The description repeats the instruction to pass the site key and points to otc_list_sites, but adds no new parameter semantics beyond the schema.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description pairs the verb 'List' with a concrete resource ('one "on the Cheap" site's article categories') and specifies returned data ('ids and post counts'). It also separates itself from siblings by explaining the site key comes from otc_list_sites and category ids feed otc_search_posts.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It tells you to pass the site key for the city and points to otc_list_sites for valid keys, routing a required prerequisite. It also explicitly frames the output as a way to filter otc_search_posts by topic, so an agent knows when and why to call this tool.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
otc_list_eventsList a city’s events for a dayARead-onlyIdempotent
List everything happening in an "on the Cheap" city on a given date, from that site’s events calendar — each with its time, price (most are free) and venue. Pass the site key for the city (see otc_list_sites) and an ISO date (YYYY-MM-DD); the date defaults to today in that city. Set free_only to keep just the no-cost listings. The national hub has no local calendar and is not a valid site here. Use otc_get_post on a listing's url for the full write-up. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| date | No | Day to list, as ISO YYYY-MM-DD. Defaults to today in the city’s own time zone. | |
| site | Yes | Which "on the Cheap" city to read. Required — there is no default site. One of: charlotte, denver, atlanta, chicago, columbus, seattle, kansascity, miami, orlando, portland, richmond, southernmaine, triangle, national. Common aliases also work (milehigh, raleigh, rva, southflorida, kc, …). Use otc_list_sites for the full list with the area each one covers. | |
| free_only | No | Only listings marked FREE |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare read-only and idempotent behavior. The description adds meaningful behavioral context: the date defaults to today in the city's time zone, the national hub is invalid, listings include time/price/venue, and the operation is read-only. No contradictions with annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Four focused sentences, front-loaded with the core action gift, then parameter notes, an exclusion, and a pointer to a sibling tool. No filler or redundant restatement of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
With no output schema, the description compensates by stating what each listing contains (time, price, venue) and the behavior of each parameter. It also covers the invalid site case and directs users to otc_get_post for full write-ups, so an agent has enough to invoke it correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Schema coverage is 100%, so the baseline is 3. The description adds value beyond the schema by explaining that `date` defaults to today, `free_only` filters to no-cost listings, and `site` must be a valid local calendar—reinforcing the schema's provided list and aliases.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: "List everything happening in an 'on the Cheap' city on a given date." It clearly distinguishes itself from siblings by noting the site-scoped calendar listing and pointing to otc_get_post for full write-ups.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
Gives explicit usage instructions: pass `site` key, use ISO `date`, set `free_only` for no-cost listings. It also mentions when not to use it (the national hub has no local calendar) and directs to otc_get_post for richer detail.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
otc_list_locationsList a city’s locationsARead-onlyIdempotent
List one "on the Cheap" site's location taxonomy with ids and post counts — the neighbourhoods and surrounding areas it covers. Pass the site key for the city (see otc_list_sites). Use an id to filter otc_search_posts geographically — ids are per-site, so use them only against the site they came from. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| site | Yes | Which "on the Cheap" city to read. Required — there is no default site. One of: charlotte, denver, atlanta, chicago, columbus, seattle, kansascity, miami, orlando, portland, richmond, southernmaine, triangle, national. Common aliases also work (milehigh, raleigh, rva, southflorida, kc, …). Use otc_list_sites for the full list with the area each one covers. |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true, openWorldHint=true, and idempotentHint=true, so the description need not repeat safety. It adds the crucial behavioral detail that ids are per-site and must only be used against the originating site, which is beyond the annotations. No contradictions found.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
Three sentences, front-loaded with the primary purpose, and every sentence earns its place: the output, the parameter usage, and the downstream use case. No fluff.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a single-parameter, read-only tool with no output schema, the description covers the essential elements: output content (ids and post counts), the parameter, the downstream use, and the per-site constraint. It is sufficient for an agent to invoke correctly.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The input schema already documents the 'site' parameter thoroughly, including allowed values and aliases, with 100% coverage. The description adds minor context (purpose of the key) but does not significantly enhance meaning beyond the schema. Baseline 3 applies.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb and resource: 'List one "on the Cheap" site's location taxonomy with ids and post counts'. It clearly distinguishes from siblings like otc_list_sites (which lists cities) and otc_search_posts (which searches posts). The purpose is unambiguous and differentiated.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly tells the agent when to use this tool: to retrieve a city's location taxonomy for filtering otc_search_posts geographically. It references otc_list_sites for the site key and warns that ids are per-site, providing clear context. While it doesn't explicitly state when not to use it, the guidance is sufficient for correct selection.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
otc_list_sitesList the On the Cheap sitesARead-onlyIdempotent
List every city in the "on the Cheap" network with the site key used to select it. This server reads them all — every other tool takes a site argument, and there is no default, so start here when you do not already know which key covers the city the user means. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
No parameters | |||
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Annotations already declare readOnlyHint=true and idempotentHint=true, so the safety profile is covered. The description adds value by stating 'This server reads them all' and 'Read-only,' reinforcing the read-only nature, and by explaining the relationship to other tools (no default site). It doesn't describe return format or pagination, but for a list-all tool with no parameters, the behavioral context is largely complete. The description does not contradict annotations.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is three sentences, each earning its place: what it lists, why it matters (site key), and when to use it. It is front-loaded with the core action and resource, and there is no fluff or repetition of the title.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For a zero-parameter, read-only list tool with no output schema, the description is complete. It tells the agent what it returns (city names and site keys), why that matters (site selection for other tools), and when to call it. The annotations cover safety and idempotency. Nothing an agent needs to invoke it correctly is missing.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
The tool has zero parameters, so the schema is trivially complete (100% coverage). The description adds meaning by explaining what the output is used for (the `site` key to select a city in other tools), which is valuable context beyond the empty schema. Baseline for 0 params is 4, and the description earns it by clarifying the purpose of the returned keys.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description states a specific verb ('List'), a specific resource ('every city in the on the Cheap network'), and the key output ('the `site` key used to select it'). It also distinguishes itself from sibling tools by explaining that this is the starting point for selecting a site, which is unique among the listed siblings.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
The description explicitly says when to use this tool: 'start here when you do not already know which key covers the city the user means.' It also explains the context that every other tool takes a `site` argument and there is no default, which effectively tells the agent to use this tool before others when site is unknown. This is clear usage guidance with an implicit alternative (other tools) and a condition.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
otc_search_postsSearch a city’s On the Cheap articlesARead-onlyIdempotent
Search and filter one "on the Cheap" site's articles — free and cheap things to do in that city, plus deals, festivals, kids activities and local guides. Pass the site key for the city (see otc_list_sites); the national hub is valid here and carries country-wide deals. Filter by full-text query, category or location id (see otc_list_categories / otc_list_locations), and publication date range. Category and location ids are per-site — resolve them against the SAME site you are searching. Retired deals live in an "expired" category and are excluded by default; set include_expired to search them too. Returns slim summaries by default — use otc_get_post for an article's full text. Read-only.
| Name | Required | Description | Default |
|---|---|---|---|
| tag | No | Tag id | |
| page | No | 1-based page number | |
| site | Yes | Which "on the Cheap" city to read. Required — there is no default site. One of: charlotte, denver, atlanta, chicago, columbus, seattle, kansascity, miami, orlando, portland, richmond, southernmaine, triangle, national. Common aliases also work (milehigh, raleigh, rva, southflorida, kc, …). Use otc_list_sites for the full list with the area each one covers. | |
| view | No | Response shape: "compact" (default) drops fields the response already carries elsewhere; "full" returns every field this server understands. compact returns slim summaries AND asks WordPress for only the fields they use; "full" returns the whole records. | |
| after | No | Only posts published on or after this date | |
| query | No | Full-text search, e.g. "free museum day" | |
| before | No | Only posts published on or before this date | |
| category | No | Category id from otc_list_categories, for this same site | |
| location | No | Location id from otc_list_locations, for this same site | |
| per_page | No | Results per page (max 100) | |
| include_expired | No | Include retired/expired deals (default false) |
TDQS
Does the description disclose side effects, auth requirements, rate limits, or destructive behavior?
Beyond the annotations (readOnly, openWorld, idempotent), the description adds crucial behavior: the default exclusion of expired deals, the effect of include_expired, the per-site nature of category/location ids, and the default slim-summary response shape. This is exactly the kind of context that prevents incorrect calls.
Agents need to know what a tool does to the world before calling it. Descriptions should go beyond structured annotations to explain consequences.
Is the description appropriately sized, front-loaded, and free of redundancy?
The description is a compact paragraph where every sentence earns its place. It front-loads the core purpose, then flows through key parameters, caveats, and the sibling handoff, without redundancies or filler.
Shorter descriptions cost fewer tokens and are easier for agents to parse. Every sentence should earn its place.
Given the tool's complexity, does the description cover enough for an agent to succeed on first attempt?
For an 11-parameter tool with no output schema, the description covers all critical aspects: site resolution, filter types, per-site id caveat, expired deals handling, default response shape, and the pointer to otc_get_post. It is complete enough for an agent to call it correctly without further investigation.
Complex tools with many parameters or behaviors need more documentation. Simple tools need less. This dimension scales expectations accordingly.
Does the description clarify parameter syntax, constraints, interactions, or defaults beyond what the schema provides?
Even though schema coverage is 100%, the description enriches parameter meaning: it explains that site keys are city-specific, that the national hub is valid, and how to resolve category/location ids via sibling tools. It also ties include_expired to the 'expired' category, which the schema alone does not convey.
Input schemas describe structure but not intent. Descriptions should explain non-obvious parameter relationships and valid value ranges.
Does the description clearly state what the tool does and how it differs from similar tools?
The description opens with a specific verb and resource ('Search and filter one site's articles') and immediately clarifies the content type ('free and cheap things to do...'). It distinguishes itself from sibling tools by explicitly routing full-text needs to otc_get_post and implying the article/event split from the sibling list.
Agents choose between tools based on descriptions. A clear purpose with a specific verb and resource helps agents select the right tool.
Does the description explain when to use this tool, when not to, or what alternatives exist?
It provides clear usage context: when to search articles, how to scope to a site, and when to use otc_get_post for full text. However, it does not explicitly state when NOT to use this tool (e.g., for events or categories listings), leaving some inference to the agent despite the sibling names.
Agents often have multiple tools that could apply. Explicit usage guidance like "use X instead of Y when Z" prevents misuse.
Tool Schema Changelog
Recent tool additions, removals, and schema changes observed during successful MCP inspections.
2 tool updates
v1.1.2- Changed
otc_events_month_overview1 field changed- changed
Input schema / properties / month / descriptionPrevious value: -"Month to summarise, as ISO YYYY-MM. Defaults to the current month."New value: +"Month to summarise, as ISO YYYY-MM. Defaults to the current month in the city’s own time zone."
- Changed
otc_list_events1 field changed- changed
Input schema / properties / date / descriptionPrevious value: -"Day to list, as ISO YYYY-MM-DD. Defaults to today."New value: +"Day to list, as ISO YYYY-MM-DD. Defaults to today in the city’s own time zone."
8 tool updates
v1.0.0- Changed
otc_events_month_overview1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
otc_get_post1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
otc_healthcheck1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
otc_list_categories1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
otc_list_events1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
otc_list_locations1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
otc_list_sites1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
- Changed
otc_search_posts1 field changed- changed
Input schema / $schemaPrevious value: -"http://json-schema.org/draft-07/schema#"New value: +"https://json-schema.org/draft/2020-12/schema"
1 tool update
v0.4.1- Changed
otc_search_posts2 fields changed- removed
Input schema / properties / compactRemoved value: -{ - "description": "Return slim summaries instead of full records (default true)", - "type": "boolean" -} - added
Input schema / properties / viewAdded value: +{ + "description": "Response shape: \"compact\" (default) drops fields the response already carries elsewhere; \"full\" returns every field this server understands. compact returns slim summaries AND asks WordPress for only the fields they use; \"full\" returns the whole records.", + "enum": [ + "compact", + "full" + ], + "type": "string" +}
2 tool updates
v0.3.3- Added
otc_healthcheck - Added
otc_search_posts
6 tool updates
v0.3.0- First observed
otc_events_month_overview - First observed
otc_get_post - First observed
otc_list_categories - First observed
otc_list_events - First observed
otc_list_locations - First observed
otc_list_sites
TDQS
Scored across 8 tools
Most tools target clearly distinct resources or actions: healthcheck, sites, categories, locations, events-by-date, events-by-month, get-post, and search-posts. The only mild overlaps are the two event tools (month overview vs single-date list) and the two taxonomy listers (categories vs locations), but the descriptions explicitly differentiate granularity and domain, so misselection risk is low.
All 8 tools share a consistent `otc_` prefix and predominantly use a `otc_<verb>_<noun>` pattern (list_sites, get_post, search_posts, list_events, list_categories). The deviations are `otc_healthcheck` (verb without noun) and `otc_events_month_overview` (noun-first, longer), which are still readable and predictable.
Eight tools is well-scoped for a read-only local-listings server: a discovery tool (list_sites), two taxonomy listers, two event views at different granularities, article search/get, and a connectivity check. Each tool earns its place with no obvious filler.
The read-only surface is largely complete: site discovery, category/location taxonomies, event listing at day and month granularity, article search and full-text fetch, plus health checking. Minor gaps exist — no cross-site aggregation or dedicated event-detail endpoint (you must route through otc_get_post) — but these are workable within the stated read-only scope.
Maintenance
Related MCP Connectors
Google Events listings with dates, venues, and ticket links via a hosted MCP server.
One MCP server for 180+ live web-data APIs returning clean JSON from sites that block scrapers.
Unofficial read-only MCP server for VeryChic hotel offers
Skiplagged MCP Server for flight search, hotel booking, and travel planning
Related MCP Servers
- AlicenseNot gradedqualityDmaintenancePreference-aware events discovery MCP server that aggregates events, restaurants, and cultural activities across multiple sources and re-ranks them against your personal taste profile to surface things you'd actually want to do.1MIT
- AlicenseNot gradedqualityCmaintenancePublic read-only MCP server backed by GetValetParking.com directory of 789 US valet parking operators across 31,186 cities. Discover valet operators by coordinates or city slug, filter by 9 service types, and fetch full operator profiles. No auth required.MIT
- AlicenseAqualityAmaintenanceRead-only MCP server for accessing Eventbrite tickets, orders, organizer data, and public event search (including undocumented consumer search via browser bridge).31550 npmMIT
- AlicenseNot gradedqualityBmaintenanceEnables listing metros and fetching events from the DoStuff network via MCP.77 npmMIT