cheaper-fuel
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., "@cheaper-fuelfind the 3 cheapest diesel stations near Leiria"
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.
cheaper-fuel
A remote MCP server for fuel prices at filling stations in mainland Portugal, running on Cloudflare Workers.
MCP endpoint |
|
Landing page | |
Health |
Data source: DGEG — Direção-Geral de Energia e Geologia.
Quick start
# Claude Code
claude mcp add --transport http cheaper-fuel https://cheaper-fuel.jorgon.workers.dev/mcp
# MCP Inspector
npx @modelcontextprotocol/inspector
# then connect to https://cheaper-fuel.jorgon.workers.dev/mcpFor Codex or any other client, add a remote MCP server pointing at the /mcp URL. The endpoint is
stateless Streamable HTTP and needs no authentication.
Related MCP server: mcp-pt
Why not scrape the website?
The public page at precoscombustiveis.dgeg.gov.pt is a JavaScript shell. Its own scripts fetch JSON
from https://precoscombustiveis.dgeg.gov.pt/api/PrecoComb/*, so this server calls that same API
instead of parsing HTML:
a stable schema instead of selectors that break on redeploy,
Access-Control-Allow-Origin: *andapplication/json,it is the exact data source DGEG serves to its own site,
robots.txtdoes not restrict/api/.
Tools
Six tools, deliberately few, so an agent does not wander between lookups.
Tool | Use it for |
| The workhorse. Cheapest stations near a place / postal code / coordinates, or within a concelho or district. Accepts friendly fuel and brand names. |
| One station: every fuel price, opening hours, services, payment methods. |
| Per-fuel min / average / median / max and price spread, nationally or regionally. |
| Daily national average prices with the change over the period. |
| Fuel catalogue (id, name, unit, road-fuel flag). |
| Resolve concelhos, localities and postal codes. |
Designed so agents make one call, not five
No prerequisite lookups. Every tool accepts human names —
"diesel","gasóleo","95","gpl","Leiria","2400-193","galp"— and resolves them internally. Numeric ids are optional.No coordinate requirement.
locationtakes a city, a locality, a postal code (2400-193or2400), or"lat,lon".One call returns everything: price, formatted display price, address, coordinates, distance, map link and freshness.
Self-widening radius. If a small concelho has too few stations,
find_stationsgrows the radius up tomax_radius_kmand reportseffective_radius_km.Server
instructionsin the MCP handshake give the model a routing table, so it picks the right tool first time.Errors terminate loops. Failures return
{ error: { code, message, hint, candidates? } }with a concrete next step instead of an empty result.
Examples
// What is diesel around Leiria right now?
{ "location": "Leiria", "fuels": ["diesel"], "limit": 3 }
// I only know my postcode.
{ "location": "2400-193" }
// Cheapest petrol 95 in Porto district, supermarkets only.
{ "district": "Porto", "fuels": ["gasolina 95"], "station_type": "supermercado", "limit": 5 }
// Prices published in the last 24 hours only.
{ "location": "Coimbra", "fuels": ["diesel"], "updated_within_hours": 24 }
// How has diesel moved this quarter?
{ "fuels": ["diesel"], "days": 90 } // get_price_historyA proximity call returns the neighbouring concelhos it covered:
"municipalities_covered": [
{ "municipality": "Leiria", "station_count": 14, "min_distance_km": 0.42 },
{ "municipality": "Marinha Grande", "station_count": 6, "min_distance_km": 8.11 },
{ "municipality": "Batalha", "station_count": 4, "min_distance_km": 11.7 }
]How it works
DGEG JSON API
└─ daily national snapshot (~14,300 station×fuel rows, paged, compacted) … cached 24 h
├─ place index → concelhos, localities, postal codes mapped to median coordinates
├─ geo → haversine, radius widening, concelho grouping
└─ MCP tools → find_stations · get_market_overview · get_station_details
PMD (daily averages) → get_price_history
GetDadosPosto → get_station_details (by id)One upstream snapshot per day powers proximity, regional and market queries. It is cached in the Cloudflare Cache API for
CACHE_TTL_SECONDS(default 86400) and memoised per isolate, so warm requests skip the ~1.8 MB JSON parse.Place resolution needs no external geocoder. The snapshot yields 278 concelhos, ~1,770 localities and ~2,680 postal codes; each gets a median coordinate.
"Neighbouring concelhos" come from geometry, not a hand-maintained adjacency table: the search radius widens until every requested fuel has enough results, and
municipalities_coveredlists exactly which concelhos were included.
Data freshness and coverage
Prices are cached for up to 24 hours. Every response carries:
data_fetched_at— when this server last read DGEG (the true cache age),last_updated(per station) ordate(per history point) — DGEG's own publication timestamp.
Treat results as as published by DGEG, never as real-time quotes.
Coverage is mainland Portugal only — 18 districts, 278 concelhos. DGEG publishes no Azores or
Madeira stations, so island coordinates return an explicit unsupported_region error rather than an
empty list.
get_price_history is national because that is the only granularity DGEG publishes; there is no
per-concelho or per-station history endpoint.
Local development
npm install
npm run dev # wrangler dev on http://127.0.0.1:8787
node test/smoke.mjs # 14 end-to-end checks against the local worker
npm run typecheck
npm testnpm run smoke -- https://cheaper-fuel.jorgon.workers.dev/mcp runs the same checks against a
deployment.
Deploy
npx wrangler deployConfiguration lives in wrangler.jsonc:
Variable | Default | Purpose |
|
| Upstream API |
|
| Cache lifetime for every upstream call |
|
| Identifying agent sent to DGEG |
To auto-deploy on push, connect the repository in the Cloudflare dashboard (Workers → Git
integration) or add CLOUDFLARE_API_TOKEN and CLOUDFLARE_ACCOUNT_ID repository secrets.
Data source, attribution and disclaimer
DGEG publishes this information free of charge for reuse, provided that:
DGEG is clearly identified as the source, and
the date and time of the last price update are shown.
Both requirements are met in every tool response (source, last_updated) and on the landing page.
Prices are reported by station operators, not measured by DGEG. This project re-publishes them as-is and guarantees nothing about their accuracy. Not affiliated with or endorsed by DGEG.
Limitations and roadmap
No per-station price history. DGEG publishes daily averages nationally only; per-station tracking would need our own D1 + cron snapshots.
No route/corridor search ("cheapest on the way to Porto").
No island coverage — upstream limitation.
Free-plan CPU: the cold parse of the daily snapshot is the heaviest request; a Workers Paid plan gives comfortable headroom.
Project layout
src/
index.ts HTTP surface: /mcp, /, /health
mcp.ts MCP server, instructions and the six tools
snapshot.ts paged national snapshot, cached and memoised
places.ts place index and name/postal-code/coordinate resolution
geo.ts haversine, radius widening, concelho grouping
dgeg.ts cache helpers, upstream client, typed errors
domain.ts pure parsing, matching and statistics
landing.ts HTML documentation page
test/
*.test.ts unit tests (vitest)
smoke.mjs end-to-end MCP client checksLicense
MIT — see LICENSE.
This server cannot be deployed
Maintenance
Related MCP Connectors
Official maximum fuel prices, effective dates and history for the Azores and Madeira.
Live official fuel station prices for France, Spain, Italy and Western Australia in one schema.
Daily station-level fuel prices for Italy from the official MIMIT feed, via Apify (pay per event).
Gas and fuel prices by station and area, as structured data via a hosted MCP server.
Related MCP Servers
- AlicenseAqualityBmaintenanceProvides real-time fuel prices at gas stations in Spain using the government's public API. Enables users to find the cheapest fuel in a municipality or list stations sorted by price.2MIT
- AlicenseAqualityCmaintenanceProvides AI assistants with live tools for Portuguese public data including fuel prices, weather, postal codes, statistics, and open data.8MIT
- AlicenseNot gradedqualityCmaintenanceEnables AI assistants to look up real-time fuel prices at over 14,000 German gas stations, find the cheapest E5, E10, or diesel near a place or GPS coordinates, and return only open stations sorted by price.MIT
- AlicenseNot gradedqualityBmaintenanceEnables querying current and historical retail petrol, diesel, and LPG prices across European countries, comparing prices by week, and checking data coverage.25 npmMIT