A small remote MCP server that exposes one tool, carpark_availability,
backed by LTA DataMall's live CarParkAvailabilityv2 feed. Built so the
ParkPilot artifact can call it through claude.ai's mcp capability and show
real available-lot counts instead of sample data.
Coverage note: LTA DataMall's carpark feed mainly covers HDB multi-storey/surface carparks and some LTA/URA lots. It does not include most private mall or office-building carparks (Suntec, Wisma Atria, Marina Bay Financial Centre, etc.) — there is no free public live-availability feed for those. So "real data" here means real HDB carpark availability near a destination, not the specific malls used in the demo.
- Go to https://datamall.lta.gov.sg/content/datamall/en/request-for-api.html
- Register with an email address and verify it.
- You'll get an
AccountKeyby email — that's yourLTA_API_KEY.
Keep this key server-side only (in the deployment's environment variables). Never put it in the artifact's HTML/JS — anyone viewing the page could read it.
npm install
cp .env.example .env # paste your key into .env
npm startThen:
curl http://localhost:8787/health
# {"ok":true,"hasApiKey":true}It needs a public HTTPS URL — claude.ai connectors are remote MCP servers. Any Node host works; Render's free tier is the least fiddly:
- In Render: New → Web Service → connect this repo (shiftedtech/parkingpilot).
- Build command:
npm install - Start command:
npm start - Add an environment variable
LTA_API_KEY= your key.
- Build command:
- Deploy. Render gives you a URL like
https://parkingpilot.onrender.com. - Your MCP endpoint is that URL +
/mcp, e.g.https://parkingpilot.onrender.com/mcp. - Check
https://parkingpilot.onrender.com/healthreturns{"ok":true,"hasApiKey":true}.
(Render's free tier sleeps after inactivity — the first request after a while takes a few seconds to wake up. Fly.io or Railway work the same way if you'd rather avoid that.)
- In claude.ai: Settings → Connectors → Add custom connector.
- Name it something like
ParkPilot LTAand paste the/mcpURL from step 3. - Save. claude.ai will call
tools/liston it and should showcarpark_availability.
Once the connector shows up in claude.ai, tell Claude (in the ParkPilot
conversation) that it's added — Claude will declare the mcp capability on
the artifact with this connector/tool and switch the app over to live HDB
carpark data near whatever destination is searched.
carpark_availability(lat?, lng?, radiusKm?, lotType?, limit?)
| param | type | notes |
|---|---|---|
lat, lng |
number | search center; omit both to get the raw feed sorted by most-available |
radiusKm |
number | only used with lat/lng, default 2 |
lotType |
"C" | "M" | "H" |
car / motorcycle / heavy vehicle, default all |
limit |
number | max rows returned, default 20, max 200 |
Returns JSON: { fetchedAt, count, totalMatched, carparks: [{ carParkId, development, area, agency, lotType, availableLots, lat, lng, distanceKm }] }.