Skip to main content
Glama
gridcarbon

gridcarbon-mcp

Official

gridcarbon clients

Official client libraries for the gridcarbon API — hourly electricity grid carbon intensity in gCO2eq/kWh for 45 zones across Europe, the United States and Great Britain.

No API key. No signup. Open CORS.

curl -s "https://api.gridcarbon.dev/v1/intensity/latest?zone=FR"
{"unit":"gCO2eq/kWh","data":[{"zone":"FR","ts":"2026-08-26T01:00:00Z","gco2eq_kwh":49,"method":"computed:v1"}]}

Package

Registry

Install

python/

PyPI gridcarbon

pip install gridcarbon

typescript/

npm gridcarbon

npm install gridcarbon

mcp/

npm gridcarbon-mcp

npx gridcarbon-mcp

Both SDKs have zero runtime dependencies — the Python one uses urllib, the TypeScript one uses global fetch. The MCP server depends on the official MCP SDK; that cost is documented in its README.

Two things to know before you use the numbers

Great Britain is measured on a different basis. GB figures come from NESO and use operational (combustion-only) emission factors — wind, solar, nuclear and hydro count as zero. Every other zone uses IPCC AR5 lifecycle factors, where those sources are not zero. GB is therefore structurally lower than a lifecycle number for the same physical grid. Do not rank GB against the other 44 zones. Both SDKs expose this as is_lifecycle / isLifecycle on every reading, and the MCP server excludes GB from rankings with an explanation rather than silently mixing bases.

"Latest" means newest published, not now. European zones typically run 2–4 hours behind and US zones 11–28 hours behind, because that is when the upstream operators publish. Every reading carries its interval start; use it rather than assuming the value is current.

The full method, the complete emission factor table, and a candid list of known biases are at gridcarbon.dev/methodology.

Related MCP server: mcp-carbon-intensity

Status

Pre-alpha. History is uneven by region: Great Britain from 2017-09, the 11 US zones from 2019-01, and the 33 European zones from 2024-08 (two years). It grows hourly. One limit is configured: 60 requests per minute per IP, loosely enforced — Cloudflare's is deliberately permissive and eventually consistent — each isolate counts separately — so bursts well above that usually succeed. Measured 2026-09-01: 150 requests in 14 seconds from one IP, no 429. Treat 60/min as the intent, not the ceiling, and do not build against the headroom. Please do not poll faster than every five minutes — that is the Cache-Control max-age on /v1/intensity/latest, and the data only changes hourly. Breaking changes are possible before 1.0; they will be noted in each package's changelog.

Attribution

The data these clients retrieve is derived from:

  • ENTSO-E Transparency Platform — European generation by production type

  • U.S. Energy Information Administration (EIA) — EIA-930 hourly generation by fuel type

  • NESO Carbon Intensity API — Great Britain

gridcarbon is not endorsed by, sponsored by, or affiliated with any of these organisations. If you redistribute or display these values, carry the same attribution.

Licence

Client code in this repository: MIT. The derived intensity values served by the API: CC BY 4.0.

The data terms, the required attribution notice, the upstream sources and their non-endorsement statements are all in DATA-LICENSE.md.

Citation

A fixed, citable snapshot of the data (1,460,467 hourly values to 2026-09-04) is archived on Zenodo: doi:10.5281/zenodo.22299989 (CC BY 4.0); the concept DOI 10.5281/zenodo.22299988 always resolves to the latest snapshot. Machine-readable metadata is in CITATION.cff at the repository root.

Contributing

Corrections to the method are genuinely welcome — especially from people who work with grid data professionally. The emission factors and their known biases are documented openly precisely so they can be argued with.

Issues and pull requests are the best channel. This repository holds the client libraries; the API backend is not open source.

Available Tools

4 tools
compare_zonesRank electricity zones by carbon intensityA
Read-onlyIdempotent

Rank several electricity zones (or all 45) by their most recently published carbon intensity, cleanest first by default.

Use it for "where should I run this training job", "is Sweden cleaner than Poland right now", "what are the five cleanest grids you cover".

Data contract (read this before you report any number to a user):

  • Unit is gCO2eq/kWh (grams of CO2-equivalent per kilowatt-hour of electricity consumed). LOWER IS CLEANER. There is no upper bound; roughly <100 is very clean, ~100-300 is moderate, >400 is fossil-heavy.

  • "ts" is the START of the reporting interval, in UTC (ISO-8601, "Z" suffix). A value with ts=2026-08-26T01:00:00Z and a 60-minute resolution covers 01:00-02:00 UTC.

  • "latest" means NEWEST PUBLISHED, NOT "now". European zones typically run 2-4 hours behind real time; US (EIA) zones run 11-28 hours behind. Every reading carries "age_minutes" and "age_human" -- state that age when you report the value. Saying "the current carbon intensity in Texas is X" about a 20-hour-old number is wrong.

  • GB values come from NESO and use OPERATIONAL (combustion-only) emission factors, not the IPCC AR5 lifecycle factors used for the other 44 zones. GB numbers are systematically lower and MUST NOT be compared or ranked against other zones.

  • Coverage starts 2026-08-21T00:00:00Z; there is no data before that date.

  • Attribution is a licence condition. If you surface these values to an end user, credit: ENTSO-E Transparency Platform / U.S. Energy Information Administration (EIA) / NESO Carbon Intensity API. EIA does not endorse this service or any use of it.

Great Britain — the one thing that makes this tool easy to get wrong: GB's numbers come from NESO and use OPERATIONAL (combustion-only) factors. The other 44 zones use IPCC AR5 LIFECYCLE factors, which also count plant construction and fuel supply chains. GB therefore looks cleaner than like-for-like. GB is EXCLUDED from the ranking by default and returned in "excluded_from_ranking" WITH its value and the reason, so you can still report it — just report it separately, never as "GB is the cleanest of these". Passing include_gb_in_ranking=true ranks it anyway and flags every affected row; only do that if the user has been told why the numbers differ.

Comparing different moments: Each zone's newest published interval has its own timestamp. European zones run 2-4h behind, US zones 11-28h behind, so a Europe-vs-US ranking compares observations taken up to a day apart. "observation_times.age_gap_minutes" reports that spread and a warning is added when it exceeds 6 hours. Say so when it applies.

Args:

  • zones (string[], optional): zone codes to rank. Omit to rank all covered zones.

  • order ("cleanest_first" | "dirtiest_first", default "cleanest_first").

  • limit (integer 1-45, default 45): cap on ranked rows.

  • include_gb_in_ranking (boolean, default false): see above.

  • response_format ("markdown" | "json", default "markdown").

Returns (structured): { "unit": "gCO2eq/kWh", "order": "cleanest_first", "comparison_basis": "IPCC AR5 lifecycle factors (GB excluded: operational factors)", "ranked_count": 3, "omitted_by_limit": 0, "ranked": [ { "rank": 1, "zone": "FR", "zone_name": "France", "gco2eq_kwh": 48.3, "ts": "2026-08-26T00:00:00Z", "age_minutes": 168, "age_human": "2h 48m ago", "freshness": "normal", "band": "very clean", "comparable": true, "method": "computed:v1" } ], "cleanest": { ... }, "dirtiest": { ... }, "spread_gco2eq_kwh": 356.1, "excluded_from_ranking": [ { "zone": "GB", "zone_name": "Great Britain", "gco2eq_kwh": 114, "ts": "2026-08-26T01:30:00Z", "age_human": "1h 18m ago", "reason": "GB uses operational (combustion-only) factors ... not comparable ..." } ], "observation_times": { "newest_ts": "...", "oldest_ts": "...", "age_gap_minutes": 90 }, "headline": "Of 3 zone(s) ranked, FR is cleanest at 48.3 gCO2eq/kWh ...", "warnings": [ ... ] }

Unknown zone codes are returned in "excluded_from_ranking" with reason "unknown zone code" instead of failing the whole call — surface them to the user, do not substitute a neighbour.

Examples:

  • "Germany, France or Spain — which is cleanest?" -> zones=["DE","FR","ES"]

  • "Five cleanest grids you cover" -> omit zones, limit=5

  • "Dirtiest US grid today" -> zones=["US-ERCOT","US-PJM","US-MISO","US-SPP","US-SOCO", "US-CAISO","US-ISONE","US-NYISO","US-BPA","US-TVA"], order="dirtiest_first", limit=1

  • Don't use for: one zone (get_carbon_intensity) or a time series (get_intensity_history).

ParametersJSON Schema
NameRequiredDescriptionDefault
limitNoMaximum ranked rows to return. Mainly useful when ranking all zones, e.g. limit=5 with order='cleanest_first' for the five cleanest grids.
orderNoSort direction. 'cleanest_first' = ascending gCO2eq/kWh (lowest emissions first).cleanest_first
zonesNoZone codes to rank, e.g. ["DE","FR","ES"]. Omit to rank every covered zone (use 'limit' to keep that readable). Unknown codes are reported back rather than silently dropped.
response_formatNoOutput format for the text content. 'markdown' is compact and human-readable; 'json' returns the full structured payload as text. Structured data is always returned alongside either way.markdown
include_gb_in_rankingNoGreat Britain uses operational (combustion-only) emission factors while the other 44 zones use IPCC AR5 lifecycle factors, so GB's number is systematically lower and ranking it against the others is misleading. By default GB is kept OUT of the ranking and reported separately with its value and an explanation. Set true only if the user has been told about the mismatch; GB is then ranked but flagged as not comparable in every row and in a top-level warning.

Output Schema

ParametersJSON Schema
NameRequiredDescription
unitYes
orderYes
rankedYes
cleanestNo
dirtiestNo
headlineYes
warningsYes
ranked_countYes
comparison_basisYes
omitted_by_limitYesZones that had data and were ranked but were cut by 'limit'. When >0, every figure in this response describes the returned rows only.
observation_timesYes
spread_gco2eq_kwhNo
excluded_from_rankingYes

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already establish readOnly, idempotent, and non-destructive behavior, so the bar is lower, but the description adds rich behavioral context: 'latest' means newest published rather than 'now', GB uses non-comparable operational factors and is excluded by default, unknown zones are returned instead of failing, and observation-time gaps are surfaced via warnings. No contradiction with the annotations exists.

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 well-structured with a one-line purpose, use cases, data contract, dedicated GB warning, args, return shape, and examples. It is long, but the complexity of the GB comparability issue and data-currency semantics justifies the length. Minor redundancy exists because the GB caveat appears in both the data contract and the dedicated GB section.

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?

The description is exhaustive for the tool's complexity: it explains units, timestamps, freshness, GB exclusion logic, unknown-zone handling, observation-time gaps, attribution requirements, coverage start, and return structure. The detailed output schema relieves the need to describe return values, and the examples cover representative ranking queries.

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 description coverage is 100%, so the schema already documents every parameter in detail, including the important include_gb_in_ranking caveat. The description's Args section largely restates defaults, though the examples add practical usage context. This meets the high-coverage baseline without adding substantial new parameter-level meaning.

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 an exact verb and resource: 'Rank several electricity zones (or all 45) by their most recently published carbon intensity, cleanest first by default.' It also names sibling alternatives in the examples ('Don't use for: one zone (get_carbon_intensity) or a time series (get_intensity_history)'), so an agent can distinguish this tool from its siblings.

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?

The description gives explicit use cases ('where should I run this training job', 'is Sweden cleaner than Poland right now') and lists when NOT to use it, naming the sibling tools directly. It also covers a critical selection rule: use this tool for ranking multiple zones, not for single-zone queries or historical series.

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

get_carbon_intensityGet latest grid carbon intensity for a zoneA
Read-onlyIdempotent

Return the most recently published carbon intensity for ONE electricity zone.

Answers questions like "how clean is the German grid right now", "should I run this batch job in Ireland or leave it", "what is the CO2 per kWh in Texas".

Data contract (read this before you report any number to a user):

  • Unit is gCO2eq/kWh (grams of CO2-equivalent per kilowatt-hour of electricity consumed). LOWER IS CLEANER. There is no upper bound; roughly <100 is very clean, ~100-300 is moderate, >400 is fossil-heavy.

  • "ts" is the START of the reporting interval, in UTC (ISO-8601, "Z" suffix). A value with ts=2026-08-26T01:00:00Z and a 60-minute resolution covers 01:00-02:00 UTC.

  • "latest" means NEWEST PUBLISHED, NOT "now". European zones typically run 2-4 hours behind real time; US (EIA) zones run 11-28 hours behind. Every reading carries "age_minutes" and "age_human" -- state that age when you report the value. Saying "the current carbon intensity in Texas is X" about a 20-hour-old number is wrong.

  • GB values come from NESO and use OPERATIONAL (combustion-only) emission factors, not the IPCC AR5 lifecycle factors used for the other 44 zones. GB numbers are systematically lower and MUST NOT be compared or ranked against other zones.

  • Coverage starts 2026-08-21T00:00:00Z; there is no data before that date.

  • Attribution is a licence condition. If you surface these values to an end user, credit: ENTSO-E Transparency Platform / U.S. Energy Information Administration (EIA) / NESO Carbon Intensity API. EIA does not endorse this service or any use of it.

Args:

  • zone (string, required): Zone code such as "DE", "FR", "US-ERCOT", "IT-NORD", "GB". Case-insensitive; unambiguous names like "Texas" or "Portugal" also resolve. Unknown zones return an error listing near matches — do NOT fall back to a neighbouring country.

  • response_format ("markdown" | "json", default "markdown"): text rendering.

Returns (structured): { "reading": { "zone": "DE", "zone_name": "Germany-Luxembourg", "source": "entsoe", "resolution_min": 60, "ts": "2026-08-26T01:00:00Z", // START of the interval, UTC "gco2eq_kwh": 371.4, "unit": "gCO2eq/kWh", "method": "computed:v1", "age_minutes": 107, "age_human": "1h 47m ago", "freshness": "normal", // fresh | normal | stale | very_stale "operational_factors_only": false, "warning": "..." // present only when something could mislead }, "as_of_statement": "As of 2026-08-26 01:00 UTC ... was 371.4 gCO2eq/kWh.", "unit": "gCO2eq/kWh", "interpretation": "371.4 gCO2eq/kWh is fossil-heavy.", "warnings": [] }

How to report the answer: Quote or paraphrase "as_of_statement". Always include the timestamp or the age. Never say "currently" or "right now" about a reading whose freshness is "stale" or "very_stale", and never about any US zone without naming the time it refers to.

Examples:

  • "How clean is France's grid?" -> zone="FR"

  • "Carbon intensity in Texas" -> zone="US-ERCOT" (freshness will be ~1 day old; say so)

  • Don't use for: comparing several zones (use compare_zones), or for a time series (use get_intensity_history).

Errors:

  • Unknown zone -> "Unknown zone "XX". ... Call list_zones ..." with suggestions.

  • Network/timeout -> a message saying the API is unreachable. Do not invent a value.

  • A covered zone with no published data yet returns "No published data for yet."

ParametersJSON Schema
NameRequiredDescriptionDefault
zoneYesZone code, e.g. 'DE' (Germany-Luxembourg), 'FR' (France), 'US-ERCOT' (Texas), 'IT-NORD', 'GB'. Case-insensitive and '_' is accepted for '-'. An unambiguous country/region name such as 'Texas' or 'Portugal' also resolves. Call list_zones if you are unsure — never substitute a neighbouring zone that is not covered.
response_formatNoOutput format for the text content. 'markdown' is compact and human-readable; 'json' returns the full structured payload as text. Structured data is always returned alongside either way.markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
unitYes
readingYes
warningsYes
interpretationNo
as_of_statementYesA ready-to-quote sentence that states the value with its as-of time.

TDQS

A4.7/5.0
Behavior5/5

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

Annotations already mark the tool readOnly/idempotent and non-destructive, so the description's job was to add behavioral nuance — and it does extensively. It discloses that 'latest' means newest published, not 'now', that readings carry age_minutes/age_human, that GB uses different emission factors and must not be ranked against other zones, that coverage starts on a specific date, and that attribution is a licence condition. This is exactly the kind of context annotations cannot express.

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?

Though long, the description is organized into clearly labeled sections — scope, data contract, Args, Returns, reporting guidance, examples, and errors. Every section earns its place: the data contract prevents the agent from reporting stale or non-comparable numbers as if they were current, and the reporting rules are actionable. The critical 'ONE zone' scope and sibling exclusions are front-loaded, not buried.

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?

For a live-data tool with real-world reporting hazards, this description is complete. It covers unit semantics, time semantics, freshness interpretation, regional factor differences, coverage start, attribution obligations, error behavior, output structure, and exactly how to phrase the answer. Combined with the rich output schema and annotations, an agent has everything needed to invoke the tool and present results safely.

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 description coverage is 100%, and the schema already documents zone codes, case-insensitivity, natural-name resolution, the 'never substitute a neighbour' rule, and response_format's enum/default. The description's Args section largely restates this information rather than adding meaning beyond the schema. It does reinforce how errors behave, but the baseline of 3 is appropriate because the schema already carries the parameter documentation burden.

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 opens with a precise verb and resource: 'Return the most recently published carbon intensity for ONE electricity zone.' It clearly distinguishes this tool from siblings by explicitly saying it is not for comparing zones or getting time series, and it gives concrete example questions such as 'how clean is the German grid right now' that an agent can match against user intent.

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?

Usage context is explicit: it lists what questions this tool answers, provides example zone mappings, and states exclusions: 'Don't use for: comparing several zones (use compare_zones), or for a time series (use get_intensity_history).' It also tells the agent to call list_zones when unsure and never substitute an uncovered neighbouring zone, leaving no ambiguity about when to pick this tool.

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

get_intensity_historyGet a carbon intensity time series for a zoneA
Read-onlyIdempotent

Return the interval-by-interval carbon intensity history for ONE zone over a time window.

Use it for "how has the German grid varied today", "what was the cleanest hour in France yesterday", "is Ireland's grid dirtier at breakfast than at midday".

Data contract (read this before you report any number to a user):

  • Unit is gCO2eq/kWh (grams of CO2-equivalent per kilowatt-hour of electricity consumed). LOWER IS CLEANER. There is no upper bound; roughly <100 is very clean, ~100-300 is moderate, >400 is fossil-heavy.

  • "ts" is the START of the reporting interval, in UTC (ISO-8601, "Z" suffix). A value with ts=2026-08-26T01:00:00Z and a 60-minute resolution covers 01:00-02:00 UTC.

  • "latest" means NEWEST PUBLISHED, NOT "now". European zones typically run 2-4 hours behind real time; US (EIA) zones run 11-28 hours behind. Every reading carries "age_minutes" and "age_human" -- state that age when you report the value. Saying "the current carbon intensity in Texas is X" about a 20-hour-old number is wrong.

  • GB values come from NESO and use OPERATIONAL (combustion-only) emission factors, not the IPCC AR5 lifecycle factors used for the other 44 zones. GB numbers are systematically lower and MUST NOT be compared or ranked against other zones.

  • Coverage starts 2026-08-21T00:00:00Z; there is no data before that date.

  • Attribution is a licence condition. If you surface these values to an end user, credit: ENTSO-E Transparency Platform / U.S. Energy Information Administration (EIA) / NESO Carbon Intensity API. EIA does not endorse this service or any use of it.

Window semantics:

  • The window is HALF-OPEN: [from, to). A point at exactly 'to' is excluded.

  • Default window is the last 24 hours. 'hours' is a shorthand for that.

  • Every point's ts is the START of its interval, in UTC. Resolution is 60 minutes for all zones except GB, which is 30.

  • There is no data before 2026-08-21T00:00:00Z, and none for intervals the upstream source has not published yet, so a window that reaches into the last few hours (or, for US zones, the last day) will simply have fewer points. Missing points are gaps, not zeros — never interpolate them.

Args:

  • zone (string, required): e.g. "DE", "FR", "US-CAISO", "GB".

  • from (string, optional): inclusive ISO-8601 UTC start.

  • to (string, optional): exclusive ISO-8601 UTC end.

  • hours (integer 1-2160, optional): last N hours ending now; ignored when 'from' is set.

  • max_points (integer, default 200): trim to the most recent N points for readability.

  • include_points (boolean, default true): false returns summary statistics only.

  • response_format ("markdown" | "json", default "markdown").

Returns (structured): { "zone": "DE", "zone_name": "Germany-Luxembourg", "source": "entsoe", "resolution_min": 60, "unit": "gCO2eq/kWh", "from": "2026-08-25T18:00:00Z", "to": "2026-08-26T00:00:00Z", "count": 6, // points the API returned for the window "server_truncated": false, // TRUE means the window is INCOMPLETE, see below "points_returned": 6, "points_omitted_for_brevity": 0, "summary": { "min": 356.5, "max": 380.7, "mean": 363.6, "first": {...}, "last": {...}, "cleanest": {"ts": "...", "gco2eq_kwh": 356.5}, "dirtiest": {"ts": "...", "gco2eq_kwh": 380.7}, "change_from_first_to_last_pct": -5.3 }, "points": [ { "ts": "2026-08-25T18:00:00Z", "gco2eq_kwh": 380.7, "method": "computed:v1" } ], "operational_factors_only": false, "warnings": [] }

Truncation — do not ignore this: The API caps a response at 5000 points. When it does, "server_truncated" is true and the series you received is only PART of the requested window. Never present a truncated series as a complete picture, and never compute a daily/weekly average from one. Narrow the window and call again instead.

Examples:

  • "Chart France's grid over the last two days" -> zone="FR", hours=48

  • "Cleanest hour in Spain yesterday" -> zone="ES", from/to spanning that UTC day, then read summary.cleanest

  • "Average intensity last week" -> hours=168, include_points=false

  • Don't use for: a single current value (get_carbon_intensity) or cross-zone ranking (compare_zones).

Errors:

  • Unknown zone -> error with near matches; call list_zones.

  • Unparseable from/to -> error naming the offending field.

  • Empty window -> a message saying no intervals were published in that range.

ParametersJSON Schema
NameRequiredDescriptionDefault
toNoWindow end, EXCLUSIVE — the window is half-open [from, to). ISO-8601 UTC, e.g. '2026-08-25T18:00:00Z'. Local times and offsets are not accepted. Omit for "up to now".
fromNoWindow start, INCLUSIVE. ISO-8601 UTC, e.g. '2026-08-25T18:00:00Z'. Local times and offsets are not accepted. Omit to use 'hours' or the default last 24h. Nothing exists before 2026-08-21T00:00:00Z.
zoneYesZone code, e.g. 'DE' (Germany-Luxembourg), 'FR' (France), 'US-ERCOT' (Texas), 'IT-NORD', 'GB'. Case-insensitive and '_' is accepted for '-'. An unambiguous country/region name such as 'Texas' or 'Portugal' also resolves. Call list_zones if you are unsure — never substitute a neighbouring zone that is not covered.
hoursNoConvenience alternative to from/to: the last N hours ending now. Ignored if 'from' is given. Example: hours=48 for the last two days.
max_pointsNoCap on how many interval points are included in the response, to keep it readable. If the window holds more, the MOST RECENT max_points are returned and the response says how many were omitted. Summary statistics are always computed over the WHOLE window, never over the trimmed subset.
include_pointsNoSet false to get only the summary statistics (min/max/mean/cleanest/dirtiest) without the individual intervals. Useful for long windows.
response_formatNoOutput format for the text content. 'markdown' is compact and human-readable; 'json' returns the full structured payload as text. Structured data is always returned alongside either way.markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
toYes
fromYes
unitYes
zoneYes
countYesPoints the API returned for the window.
pointsYes
sourceNo
summaryNo
warningsYes
zone_nameNo
resolution_minNo
points_returnedYes
server_truncatedYesTrue if the API hit its 5000-point cap and the window is INCOMPLETE.
server_truncation_noteNo
operational_factors_onlyYes
points_omitted_for_brevityYes

TDQS

A4.6/5.0
Behavior5/5

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

Annotations already declare readOnlyHint=true, idempotentHint=true, and destructiveHint=false, so the safety profile is covered. The description adds substantial behavioral context: the unit meaning (gCO2eq/kWh, lower is cleaner), the distinction between 'latest' (newest published) and 'now', the GB operational-factor caveat, the data-start boundary, the half-open window semantics, truncation behavior (server_truncated true means incomplete), and the rule never to interpolate missing points. This goes far beyond the annotations and is essential for correct interpretation.

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 long, but every section is purposeful and well factored: a one-sentence purpose, examples, data contract, window semantics, args, return structure, truncation warning, and errors. It is front-loaded with the core purpose and examples, and the headings make it scannable. While it could be trimmed, no sentence is redundant; given the tool's complexity (7 parameters, return contract, error cases), the length is justified. This is strong structure, though not as lean as a two-sentence description.

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?

Given the tool's complexity, the description is exceptionally complete. It covers parameter usage, return structure with a concrete JSON example, window semantics, truncation handling, error messages, attribution licensing, and even the caveat about missing points. It also explains the summary statistics and how to use them, and notes that max_points trimming does not affect summary statistics. The output schema is provided, but the description adds operational context (like server_truncated) that is not in the schema. Nothing an agent needs to call this tool correctly is omitted.

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?

The input schema has 100% description coverage, documenting each parameter's format, defaults, and constraints (e.g., 'EXCLUSIVE' for 'to', 'Ignored if from is given' for 'hours'). The description does not add meaning beyond what the schema already provides for the parameters themselves; it reiterates the same semantics. The only incremental value is clarifying the default window and the 'hours' shorthand, but those are also mentioned in the schema ('hours' description mentions 'the last N hours'). With full schema coverage, a baseline of 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 opens with a specific verb and resource: 'Return the interval-by-interval carbon intensity history for ONE zone over a time window.' It explicitly scopes to a single zone, distinguishing it from cross-zone tools, and provides concise example queries ('how has the German grid varied today') that anchor the purpose. This is unambiguous and immediately differentiates the tool from siblings like compare_zones.

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?

The description explicitly states when to use the tool via example intents ('what was the cleanest hour in France yesterday') and then explicitly lists exclusions: 'Don't use for: a single current value (get_carbon_intensity) or cross-zone ranking (compare_zones).' It names the sibling alternatives and the conditions that disqualify them, leaving no ambiguity about routing.

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

list_zonesList covered electricity zonesA
Read-onlyIdempotent

List every electricity zone gridcarbon covers, with its upstream data source, its reporting resolution, and whether its numbers are comparable with the rest.

Call this whenever you are not certain a zone code exists. The data tools reject unknown codes on purpose — there is no sensible fallback, and substituting a neighbouring country's grid would be a fabrication.

Coverage is 45 zones: continental Europe + Nordics + Ireland (ENTSO-E), 10 US balancing authorities plus a Lower-48 aggregate (EIA), and Great Britain (NESO). There is NO coverage of Canada, Australia, Japan, China, India, Latin America or Africa.

This tool returns no measurements itself, but the values the other tools return follow one contract: the unit is gCO2eq/kWh and LOWER IS CLEANER; each value's "ts" is the START of its reporting interval in UTC; and "latest" means NEWEST PUBLISHED, NOT "now" — see typical_lag_hours below and always quote the timestamp with the number.

Two things this list tells you that matter for correctness:

  • factor_basis: "lifecycle" for 44 zones (IPCC AR5, includes construction and fuel supply chain) versus "operational" for GB (combustion only). GB values come from NESO and use OPERATIONAL (combustion-only) emission factors, not the IPCC AR5 lifecycle factors used for the other 44 zones. GB numbers are systematically lower and MUST NOT be compared or ranked against other zones.

  • typical_lag_hours: how far behind real time that source normally publishes. US zones are routinely ~1 day behind. This is normal, not an outage — but it means a US value must never be described as "right now".

Args:

  • source ("entsoe" | "eia" | "uk-neso", optional): filter by upstream provider.

  • search (string, optional): case-insensitive substring over zone code and name.

  • response_format ("markdown" | "json", default "markdown").

Returns (structured): { "count": 45, "total_covered": 45, "zones": [ { "zone": "DE", "name": "Germany-Luxembourg", "source": "entsoe", "resolution_min": 60, "factor_basis": "lifecycle", "typical_lag_hours": 4, "comparable_with_others": true }, { "zone": "GB", "name": "Great Britain", "source": "uk-neso", "resolution_min": 30, "factor_basis": "operational", "typical_lag_hours": 2, "comparable_with_others": false } ], "history_starts_at": "2026-08-21T00:00:00Z", "notes": [...] }

Examples:

  • "Which US grids do you cover?" -> source="eia"

  • "Do you have Italy?" -> search="italy" (returns the 7 Italian bidding zones)

  • "Is Japan supported?" -> search="japan" returns zero rows; say it is not covered.

ParametersJSON Schema
NameRequiredDescriptionDefault
searchNoCase-insensitive substring filter over the zone code and the zone name, e.g. 'italy', 'NO-', 'iso'.
sourceNoOnly return zones from this upstream source. 'entsoe' = Europe, 'eia' = United States, 'uk-neso' = Great Britain.
response_formatNoOutput format for the text content. 'markdown' is compact and human-readable; 'json' returns the full structured payload as text. Structured data is always returned alongside either way.markdown

Output Schema

ParametersJSON Schema
NameRequiredDescription
countYes
notesYes
zonesYes
total_coveredYes
history_starts_atYes

TDQS

A4.8/5.0
Behavior5/5

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

Annotations already declare readOnly, idempotent, and openWorld hints, and the description adds substantial behavioral context beyond them: the gCO2eq/kWh unit contract, 'latest' means newest published not 'now', typical_lag_hours semantics, and the lifecycle-vs-operational factor_basis distinction. It also warns that GB numbers must not be ranked against the other 44 zones, which is critical correctness information.

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 long but well-organized, front-loading the core purpose and then layering caveats and examples. Most sentences earn their place because they convey correctness-critical semantics. However, the GB operational-factor point is repeated in close proximity, so it could be tightened slightly without losing information.

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?

For a discovery/registry tool with three optional parameters and an existing output schema, the description is exceptionally complete. It covers coverage scope, unsupported regions, filter behavior, return contract, caveats about lag and factor_basis, and example invocations. An agent has everything needed to call this tool correctly and interpret its results.

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 description coverage is 100%, so the structured definitions already document all three parameters. The description adds value beyond the schema with usage examples, coverage mapping (entsoe/eia/uk-neso to regions), and the note that searching for an unsupported country returns zero rows and should be reported as not covered. This exceeds the baseline but is not exhaustive about edge-case behavior.

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 opens with a specific verb and resource: 'List every electricity zone gridcarbon covers,' and enumerates the exact attributes returned (upstream data source, reporting resolution, comparability). It also disambiguates from the sibling measurement tools by explicitly stating 'This tool returns no measurements itself,' so an agent can distinguish it from get_carbon_intensity and get_intensity_history.

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?

The description gives an explicit trigger: 'Call this whenever you are not certain a zone code exists.' It explains why the data tools reject unknown codes and warns that substituting a neighboring country's grid would be a fabrication. It also gives concrete examples mapping user questions to filters, such as 'Which US grids do you cover?' -> source='eia'.

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. Dates show when Glama detected each change.

  1. 4 tool updatesv0.1.2
    • First observedcompare_zones
    • First observedget_carbon_intensity
    • First observedget_intensity_history
    • First observedlist_zones

TDQS

A4.8/5.0
Disambiguation5/5

Each tool has a clearly distinct purpose: single latest reading, historical series, zone metadata listing, and cross-zone comparison. The descriptions actively cross-reference the other tools with 'Don't use for' guidance, making misselection very unlikely.

Naming Consistency5/5

All tool names follow a consistent verb_noun pattern in snake_case: get_carbon_intensity, get_intensity_history, list_zones, compare_zones. The verbs (get, list, compare) are descriptive and match each tool's function.

Tool Count5/5

Four tools is well-scoped for a read-only carbon intensity API. Each tool earns its place with no redundancy, and the count falls comfortably within the ideal 3-15 range.

Completeness5/5

The tool surface covers the full read lifecycle: zone discovery (list_zones), current value (get_carbon_intensity), cross-zone comparison (compare_zones), and historical time series (get_intensity_history). No CRUD operations are needed for this domain, and forecast is not part of the stated data contract, so there are no obvious gaps.

Maintenance

ActivityMaintained
ResponsivenessNo issues

Related MCP Connectors

Related MCP Servers

  • A
    license
    Not graded
    quality
    D
    maintenance
    Provides real-time US power grid intelligence and carbon intensity data to enable carbon-aware AI compute scheduling across major grid regions. It allows users to monitor energy generation and optimize workloads based on renewable energy availability and grid load forecasts.
    2
    MIT
  • A
    license
    Not graded
    quality
    D
    maintenance
    Enables users to query the UK National Grid's carbon intensity data, providing real-time and forecasted carbon emissions for electricity generation.
    14
    MIT
  • A
    license
    A
    quality
    D
    maintenance
    Provides real-time electricity grid data including CO2 intensity, power mix, and wholesale prices, plus optimal green time windows for energy-intensive AI tasks. Supports UK, Germany, and global regions with optional API keys.
    9
    MIT
  • A
    license
    B
    quality
    A
    maintenance
    Provides real-time European and GB electricity grid data via MCP, including generation, prices, carbon intensity, and grid infrastructure.
    44
    48
    6
    MIT

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/gridcarbon/clients'

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