Skip to main content
Glama
cobus-meyer

table-mountain-mcp

by cobus-meyer

table-mountain-mcp

An MCP server that lets an agent answer "should I go up Table Mountain today?" and "which day this week is best?" using tablemountainweather.com, which I built.

It ships with an eval suite, because a tool description is the agent's only documentation and the only way to know whether it works is to watch agents use it.

Tools

Tool

Use it for

Returns

get_table_mountain_today

Today or right now: going up, hiking, the cable car, wind on top

Go/no-go verdict, reasons, warnings, summit conditions, cable car status and hours, a better day if there is one

find_best_day

"Which day is best?", "Is Saturday any good?"

The 7-day forecast ranked best first, dates outside the forecast, and a cable car note if it's closed

Both are read-only and call one public endpoint, GET https://tablemountainweather.com/api/verdict, cached for five minutes (the site refreshes every ten).

Related MCP server: bergauf

Design decisions

  • Freshness is part of the answer. Every result has a freshness block: when the data was observed, its age, the Cape Town date it was made for, and stale: true with a plain-language note if it's old or from another day. While building this, the live endpoint served a verdict observed the previous day. An agent reading "verdict: no" without that context would give the wrong advice with full confidence.

  • "Today" means today in Cape Town, not on the agent's server. Cape Town is UTC+2, so at 23:30 UTC it is already tomorrow there. There's a test for that.

  • Say what's missing instead of dropping it. Dates past the 7-day forecast come back in notInForecast, so the agent says "no forecast yet" rather than silently answering about other days.

  • Errors tell the agent what to do. When the site is down the tool returns an error that says not to estimate the weather and where the user can check.

  • Weather and the cable car are separate questions. A good-weather day while the cableway is closed for maintenance gets a cablewayNote.

  • Defensive parsing. The response is validated with Zod and unknown fields pass through, so a site change produces a clear error rather than wrong numbers.

Install

Requires Node 20+.

git clone https://github.com/cobus-meyer/table-mountain-mcp && cd table-mountain-mcp
npm install && npm run build

Claude Code:

claude mcp add table-mountain -- node /absolute/path/to/table-mountain-mcp/dist/index.js

Claude Desktop, Cursor or any stdio MCP client:

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

Tests

npm test

Tests drive the server through a real MCP client over an in-memory transport: ranking, stale data, the Cape Town midnight edge, out-of-range dates, a closed cableway, a site outage, bad input, caching and a changed response shape.

Evals

evals/cases.ts holds 12 questions a real user would ask, each run against a frozen API response and a frozen clock:

Case

What it checks

today-no, today-yes

Gives the verdict and a better day

wind, last-car

Reads conditions and cable car hours correctly

best-this-week, saturday, weekend

Converts weekday names to dates, ranks, reports a poor day honestly

out-of-range

Says a date is beyond the forecast instead of guessing

stale

Notices the verdict is from yesterday

cableway-closed

Good weather, but mentions the closure

site-down

Admits it couldn't check, invents no numbers

wrong-place

Doesn't use Table Mountain data for Johannesburg

Each case starts a fresh agent with the server attached and grades the transcript: were the right tools called, does the answer contain the facts that matter, and does it avoid the mistakes that matter. Grading is rule-based on purpose so it's cheap, repeatable and easy to dispute.

npm run eval:check                                   # offline: cases, fixtures and tools are valid
ANTHROPIC_API_KEY=... npm run eval                   # run all cases once
npm run eval -- --runs 3 --model claude-haiku-5-5    # repeat to see variance
npm run eval -- --descriptions baseline              # compare one-line tool descriptions

--descriptions baseline swaps in the one-line tool descriptions most servers ship, so the effect of writing descriptions for agents can be measured instead of assumed. Results are written to evals/results/.

Results

12 cases, 3 runs each, on claude-haiku-5-5, run on 2026-11-03.

Description set

Pass rate

Avg tool calls

v1

100% (36/36)

1.0

baseline

92% (33/36)

0.9

The only failure was last-car on baseline, in all 3 runs: the agent said it had no access to the cable car schedule and never called a tool, because the one-line description only mentions a weather verdict. v1 names cable car status and hours in its description and passed all 3 runs. With no v1 failures, nothing changed after these runs.

Fixtures

fixtures/windy-monday.json is a real response from the live API. calm-monday.json and cableway-closed.json are edited copies of it for cases the live API wasn't showing at the time.

License

MIT

Available Tools

2 tools
find_best_dayBest day to go up Table MountainA
Read-onlyIdempotent

Rank the days in tablemountainweather.com's 7-day Table Mountain forecast, best first. Each day has a quality rating (best to worst: excellent, good, grey, poor, blocked) and goodHours, the number of hours that day rated good for going up. Use for 'which day is best', 'is Saturday any good', or planning a trip this week. Pass dates for specific days, or from/to for a range; with no arguments it ranks every remaining day. Convert weekday names to YYYY-MM-DD using freshness.todayInCapeTown from any earlier result, or call with no arguments and read the weekday field. Dates outside the forecast come back in notInForecast: say there's no forecast for them yet instead of guessing. If cablewayNote is set, mention it.

NameRequiredDescriptionDefault
toNoLast date to include, YYYY-MM-DD (Cape Town).
fromNoFirst date to include, YYYY-MM-DD (Cape Town). Defaults to today.
datesNoSpecific dates to rate, YYYY-MM-DD (Cape Town). Overrides from/to.

TDQS

A4.6/5.0
Behavior5/5

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

Annotations only cover safety (readOnly, idempotent, openWorld); the description adds substantial behavior beyond them: the rating scale, `goodHours`, the `notInForecast` fallback for out-of-range dates, the `cablewayNote` caveat, and the dependency on `freshness.todayInCapeTown` for weekday-to-date conversion.

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?

Front-loaded with the core action and rating scale, then argument guidance, then edge-case handling; nearly every sentence carries instructions the agent needs at call time. It runs a bit long, but no sentence is filler.

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

Completeness5/5

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

There is no output schema, and the description compensates by naming every meaningful return field (quality, goodHours, notInForecast, cablewayNote, weekday) and telling the agent how to phrase results. Nothing needed to call or interpret it is missing.

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 coverage is 100%, so baseline is 3, and the description adds real meaning on top: precedence between `dates` and `from`/`to` and the no-argument default of ranking every remaining day. The weekday-name conversion workflow is value the schema cannot express.

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?

States a specific verb and resource ('Rank the days ... 7-day Table Mountain forecast, best first') and enumerates the rating vocabulary up front. The 7-day ranking scope implicitly separates it from the today-only sibling, so an agent can pick correctly without opening the schema.

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?

Gives concrete triggering phrasings ('which day is best', 'is Saturday any good') plus explicit argument-selection rules: use `dates` for specific days, `from`/`to` for a range, nothing to rank all remaining days. It never names the sibling `get_table_mountain_today` as the alternative for today's conditions, so the when-not guidance is incomplete.

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

get_table_mountain_todayTable Mountain todayA
Read-onlyIdempotent

Should someone go up Table Mountain (Cape Town) TODAY? Returns tablemountainweather.com's go/no-go verdict with reasons, warnings, current summit conditions (wind, gusts, cloud, rain, temperature), cable car status and hours, and a better day this week if there is one. Use for questions about today or right now: going up, hiking, the cable car, wind or cloud on top. For a specific day other than today, or 'which day is best', use find_best_day instead. Only covers Table Mountain. Don't use it for other places. Times are Cape Town local time (UTC+2). Check freshness.stale: if true, follow freshness.note and don't present the data as current. If cableway.running is false, cableway.closedUntil is the date it reopens, not its last closed day.

NameRequiredDescriptionDefault

No parameters

TDQS

A4.8/5.0
Behavior5/5

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

Annotations only declare readOnly/idempotent/openWorld, so the description carries the real burden and does so: it enumerates the returned fields (verdict, reasons, warnings, summit wind/gusts/cloud/rain/temperature, cable car status and hours), pins the timezone (UTC+2), and defines a data-freshness contract (check freshness.stale, follow freshness.note, don't present as current). It also disambiguates cableway.closedUntil as a reopen date rather than a last-closed date, which is exactly the kind of trap a naive reader would fall into.

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?

Front-loaded with the core question and the verdict payload, then usage, then scope, then caveats — a sensible ordering with no filler sentences. It runs slightly long and the freshness/cableway caveats are dense, but each clause encodes a distinct rule an agent would otherwise get wrong.

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

Completeness5/5

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

With no output schema, the description takes responsibility for describing the return payload, including conditional fields ('a better day this week if there is one'). Combined with the freshness and closedUntil semantics, an agent has everything needed to call it and interpret the result without further documentation.

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?

The tool takes zero parameters, so per the baseline this sits at 4; there is no parameter meaning left to add. The description does not waste words restating an empty schema, which is the right call.

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 opening sentence states a specific question-shaped verb ('Should someone go up Table Mountain TODAY?') plus the resource, verdict type, and the exact site the data comes from. It explicitly distinguishes itself from the sibling by naming find_best_day for other days, and scopes itself geographically ('Only covers Table Mountain').

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?

Gives explicit when-to-use ('questions about today or right now: going up, hiking, the cable car, wind or cloud on top'), explicit routing to the alternative ('For a specific day other than today, or "which day is best", use find_best_day'), and explicit exclusions ('Don't use it for other places'). All three routing decisions an agent needs are stated.

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.

  1. 2 tool updatesv0.1.0
    • First observedfind_best_day
    • First observedget_table_mountain_today

TDQS

A4.6/5.0

Scored across 2 tools

Disambiguation5/5

The two tools split cleanly along a temporal axis: get_table_mountain_today answers 'right now / today' while find_best_day ranks the 7-day forecast. Each description explicitly tells the agent when to use the other tool, leaving essentially no room for misselection.

Naming Consistency4/5

Both names are snake_case verb_phrase constructions that describe their output, but the verbs differ (get_ vs find_) and only one carries the domain prefix (table_mountain). Still highly predictable once the pair is seen together.

Tool Count4/5

Two tools is thin by generic standards, but the domain is deliberately narrow — a single site's daily go/no-go verdict — and the today/forecast split covers it without padding. Nothing here feels like filler, though a third tool would not have room to exist.

Completeness4/5

Today's verdict (with conditions, cableway status, warnings, staleness) plus a ranked 7-day outlook with date filtering covers the realistic user intents for this niche. Remaining gaps — hourly breakdowns, historical trends, other trailheads — are minor or explicitly out of scope.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • F
    license
    Not graded
    quality
    D
    maintenance
    Enables AI agents to access real-time and historical weather data through multiple weather APIs including OpenMeteo, Tomorrow.io, and OpenWeatherMap. Provides comprehensive meteorological information including current conditions, forecasts, historical data, and weather alerts.
    -
  • F
    license
    Not graded
    quality
    D
    maintenance
    Lets an LLM plan hikes anywhere in Switzerland by combining named routes, elevation profiles, weather forecasts, and public transport.
    7
    -
  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides weather intelligence as MCP tools (current weather, forecast, air quality, UV index, alerts) with agentic orchestration, memory, and citation-grounded RAG.
    MIT