# mccarbon: a personal carbon ledger for a year of McDonald's orders

> mccarbon is a MIT licensed Python tool that pulls a year of McDonald's orders through the official MCP, splits the carbon estimate into food, packaging and delivery layers with published factors behind each one, and renders a single self-contained HTML ledger plus a what-if reducer. It suits a curious customer of one chain, and its numbers are estimates by design.

**yeqv111/mccarbon** — 麦麦碳账本 · 基于麦当劳 MCP 的个人餐饮碳足迹估算与减排模拟器 | Personal dining carbon footprint estimator powered by McDonald's MCP

- Repository: https://github.com/yeqv111/mccarbon
- Stars: 935 · Forks: 37
- Language: Python
- License: MIT
- Published: 2026-10-22 · Updated: 2026-10-22 · Language: en
- Canonical page: https://hysenlabs.com/projects/yeqv111-mccarbon

## What the tool actually computes

The project describes itself as a personal dining carbon footprint estimator powered by McDonald's MCP, and its stated theme is that your McDonald's order for a year emitted a certain amount of carbon, and what you could switch to in order to emit less. Saving money, calories and ordering are explicitly not the subject.

What it produces is a single-file HTML carbon ledger. The contents are described in the README: the total carbon footprint, a carbon grade from A to E, the three-layer breakdown, a monthly curve, the heaviest carbon category, the single heaviest order, an intuitive conversion such as how many trees or how many kilometres of driving that equates to, and a reduction simulator.

The layer model is the core idea, and the README is explicit that the three layers are an accounting model with a stated share. The food layer accounts for roughly 90 percent of the total. The packaging layer covers the container, the cutlery and the bag. The delivery layer covers the ride.

That split is what makes the output useful rather than a single number. It immediately tells you which lever matters, and the last layer is the interesting one, since a takeaway order carries the packaging cost of the food plus the packaging cost of the delivery, while a collection order carries only the first.

The audience is a developer who orders from one chain and is curious about the arithmetic, and the tooling choices, a Python package with a console script, reflect that it was built as an entry for a competition rather than as a product.

## The factors, and how the food layer is estimated

The README is unusually explicit about methodology, on the stated reasoning that a carbon footprint project is most vulnerable to the accusation that the numbers were invented. Every factor is in a single file, src/mccarbon/factors.py, and can be checked one by one.

For the food layer, the primary source is the Vegan Society's Plate Up For The Planet study of measured United Kingdom McDonald's items, and the README lists the values in kilograms of CO2 equivalent per serving: a Double Big Mac at 4.46, a Quarter Pounder at 2.99, a Big Mac at 2.35, twenty McNuggets at 2.13, a Filet-O-Fish at 0.82, a McPlant at 0.29, a McFlurry at 0.17 and a large fries at 0.15. Items carrying a measured value are marked as such.

Two database values support the rest. ADEME's Agribalyse database gives a fast food burger life cycle value of 18.6 kg CO2e per kilogram of finished product, of which the agricultural step accounts for 92.5 percent. And the European Union beef life cycle assessment is 23.5 kg CO2e per kilogram, more than twenty times that of pulses or potatoes, which is the stated reason swapping protein is the most effective lever.

For the large majority of Chinese menu items there is no public measured value, so the tool extrapolates from the median of the carbon category. The category medians given are beef 2.40, chicken 1.00, fish 0.80, plant-based 0.30 and snacks 0.35 kg CO2e per serving. The README argues this is steadier than forcing the British single-item data onto a Chinese menu, and easier to explain.

There is a matching rule for names, longest keyword first, so a double Big Mac is not claimed by the Big Mac entry.

## Packaging and delivery, and where the actionable saving is

The packaging layer is drawn from the Chinese product life cycle greenhouse gas emission coefficient database, and the README gives three per-item values: a polypropylene food container of 650 millilitres and 23 grams at about 186.18 g CO2e per unit, a set of disposable cutlery at about 54 g, and a 6 gram plastic bag at about 19 g. The costs are then apportioned by channel, with delivery ordering heavier than eating in or collecting, because the delivery case includes all three items.

The delivery layer references domestic and international food delivery research, giving an average of 111.80 g CO2e per order, of which packaging accounts for 86 percent and the delivery leg itself only about 15.6 g, with electric two-wheelers doing most of the work. The conclusion the README draws is that collecting in person almost erases the delivery layer, which makes it one of the highest value reduction actions available.

That is a good illustration of why the three-layer split is the design decision that matters. The food layer is roughly 90 percent of the total and is mostly fixed by what you eat. The delivery layer is small and mostly fixed by how you collect. The packaging layer sits in between, is entirely under the user's control through the choice between eating in, collecting and ordering in, and is large enough to be worth a simulator.

The simulator offers the substitutions the README lists: red meat to white meat, delivery to collection, smaller sides, dessert halved, and breaking up a combo. Each one outputs how many kilograms it would save and what share of the total that is.

The conversion constants are stated for the intuitive framing: a mature tree absorbs about 21 kg of CO2 a year, and a petrol car is about 170 g of CO2 per kilometre.

## Running it offline first, then with a real token

The quick start is three commands, and the second one needs nothing at all, no dependencies, no token and no network access:

```bash
PYTHONPATH=src python3 -m mccarbon demo
```

The demo uses built-in sample data for a full year of 2026, and it is described as a way to see the effect with zero token. Generating the shareable HTML report from the same offline data is the same command with two extra flags:

```bash
PYTHONPATH=src python3 -m mccarbon --mock --html carbon-book.html
```

If the PYTHONPATH prefix is annoying, the package installs and gives you a short command:

```bash
pip install .
mccarbon demo
```

The environment requirement is Python 3.9 or newer, with zero third-party dependencies. The README states it was tested on 3.9.6 and 3.13.12, and the only things used are the standard library modules urllib, datetime, html and json. The pyproject declares requires-python >=3.9, the MIT licence, a beta development status, and a console entry point named mccarbon.

One detail worth flagging: the clone command in the README points at a different GitHub account than the repository this article covers, so the URL to clone is the one the README itself prints, and the version numbers in the two places do not obviously track each other.

The offline path is genuinely useful, and not only as a demo. It is how you can look at the shape of the output and the size of the numbers before deciding whether the live path is worth handing a token to.

## The token flow, and the account command that checks it

Real data comes from the official McDonald's MCP, and the README names the calls it uses: order-list for the order history, query-order for a single order, list-nutrition-foods for nutrition data and query-my-account for the loyalty account.

You need a token first, applied for through the M-China mcd-mcp-server project, and it can be supplied in two ways, as an environment variable or on the command line:

```bash
export MCD_MCP_TOKEN="your_token"
```

```bash
PYTHONPATH=src python3 -m mccarbon account --token "your_token"
```

The README recommends validating the token first, and the account subcommand is the way to do it. It prints the membership card number and the points balance, which means the token works; a 401 means the token is invalid or expired.

That is a good design choice, because it separates authentication from the expensive part. A token failure should cost you one cheap call, not a full order pull.

The real run then looks like this:

```bash
PYTHONPATH=src python3 -m mccarbon --live --html carbon-book.html --token "your_token"
```

The precedence rules are spelled out in the README and are worth reading carefully. The --mock flag forces offline mode, while --live, --token or the MCD_MCP_TOKEN environment variable force the real path, and if none of them are given the tool detects a token and uses the real path, otherwise falling back to mock. So an ambient token in your environment silently switches the tool from sample data to your actual order history, which is convenient and also a thing to be aware of.

On privacy, the README notes that the membership card number is masked by default so that a shared screenshot does not leak the account.

## The four subcommands and the single-file report

The command surface is small and each subcommand does one thing.

The report subcommand is the default and generates the carbon ledger, with the common options being the output path for HTML, the output path for JSON, a start and end date, a name, a city, a token and a detail flag. The demo subcommand runs the same report on the offline sample data. The export subcommand only writes the normalised order JSON, which is the useful one if you want to feed the data somewhere else. The account subcommand only reads and prints the real membership account, which is the token validation step.

The exported JSON is worth noting because it is the seam between the data source and the accounting. Everything downstream, the factors, the simulator and the report, works from that normalised form, so you can inspect it and reason about it without re-pulling from MCP.

The HTML report is generated by report.py and the module list in the README shows the division of labour: factors.py holds the emission factors and the ingredient categorisation, carbon.py is the three-layer accounting engine, reduce.py is the simulator, models.py holds the Order and OrderItem data models, nutrition.py parses the official nutrition table and classifies dishes, mcp_client.py is a zero-dependency MCP Streamable HTTP client, source.py abstracts the MCP data source and parses tolerantly, mock_data.py holds the 2026 sample orders, render.py prints a terminal version of the ledger, and cli.py is the entry point.

The report is a single HTML file with no external CDN and no chart library, so opening carbon-book.html by double-clicking it gives a self-contained page you can screenshot as a long image. The charts are inline SVG, the donut and the monthly bars, with no script and no network dependency. The reason is stated in the README: the whole point of a shareable ledger is that it keeps working when you send it to someone.

## A factor table as data, and the line the project refuses to cross

Two design decisions in the README are worth separating out, because they are what make the numbers arguable rather than merely plausible.

The first is that the factor table is data and not code. Adding a dish means adding a row to DISH_FACTORS, and adding a category means adding a row to CATEGORY_SERVING_KG. The accounting engine does not change. That means a reviewer who disagrees with a number can change that number and re-run, rather than reimplementing the model, and it is why the factor file is the natural place to look when a result surprises you.

The second is a stated boundary on what the tool is allowed to say. The reduction module outputs how many kilograms a substitution would save and does not make value judgements for the user, which the README describes as a line a carbon project has to hold, in the sense of not doing greenwashing. The distinction is between telling someone that switching from beef to chicken removes 1.4 kg of CO2 from their year, and telling them that they should stop eating burgers.

The disclaimer is equally explicit. The ledger is an estimate, not data disclosed by McDonald's, intended for comparison across options and for judging direction of travel, and actual values will differ by region, supply chain and packaging specification.

The project is a contest entry for the McDonald's developer competition and is explicitly not an official McDonald's product, and there is a CONTEST_DECLARATION.md file in the repository marked as the original submission that should not be altered. The licence is MIT, and the last push was on 2026-10-13.

## Conclusion

mccarbon fits a developer who wants to see what their own ordering habits cost in carbon, and who accepts a transparent estimate built from published factors rather than a vendor figure, because the factor table lives in one readable file and every layer can be checked line by line. It is the wrong choice for an emissions report, for a footprint that has to survive an audit, and for anyone whose ordering is spread across many chains, since the data source is one MCP. Before you run it against a real token, start with the offline demo, then the account subcommand to confirm the token works, and read the methodology in the README rather than the numbers in the output, because the disclaimer in the project is that these are estimates and not official disclosures.

## FAQ

### What does mccarbon estimate?

It estimates the carbon footprint of your McDonald's orders over a period, split into three layers, food at roughly 90 percent of the total, packaging and delivery, and produces a single-file HTML ledger with a carbon grade from A to E, a monthly curve and a reduction simulator.

### How do I run mccarbon without a McDonald's token?

Run PYTHONPATH=src python3 -m mccarbon demo, which uses the built-in 2026 sample orders and needs no network access. Adding --mock --html carbon-book.html writes the same offline data to a shareable report.

### Where does mccarbon get its emission factors?

Measured United Kingdom values from the Vegan Society Plate Up For The Planet study for individual items, ADEME Agribalyse life cycle values for fast food burgers, the European Union beef life cycle assessment, and the Chinese product life cycle greenhouse gas emission coefficient database for packaging, with everything collected in src/mccarbon/factors.py.

### How do I check that my McDonald's MCP token works?

Run the account subcommand with your token, for example PYTHONPATH=src python3 -m mccarbon account --token "your_token". If it prints the membership card number and points, the token is valid, and a 401 means it is invalid or expired.

### Does mccarbon need any third-party Python packages?

No. The project uses only the standard library modules urllib, datetime, html and json, and the requirements.txt file is an empty placeholder. The package requires Python 3.9 or newer and installs a console script named mccarbon.

## Sources

- [Issues](https://github.com/yeqv111/mccarbon/issues)
- [License: MIT](https://github.com/yeqv111/mccarbon/blob/main/LICENSE)
- [README](https://github.com/yeqv111/mccarbon/blob/main/README.md)
- [yeqv111/mccarbon on GitHub](https://github.com/yeqv111/mccarbon)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/yeqv111-mccarbon
