GAEB tender in Claude Desktop: pyGAEB MCP setup and real answers
Connect the pyGAEB MCP server to Claude Desktop, ask an estimator's questions about a GAEB bid and read the real answers — plus the bugs the test found.
Two months ago we announced that pyGAEB ships a Model Context Protocol server. That post explained what it is. This one is the follow-up we owed: we sat down with Claude Desktop, a folder of bid files, and the questions an estimator actually asks, and wrote down what came back — including the parts where our own tools got it wrong, and what we changed.
The short version: the setup takes five minutes, the answers are good, and the test found sixteen bugs in the server that are now fixed in pyGAEB 1.18. If you want the setup only, the first section is all you need.
Setting up the pyGAEB MCP server in Claude Desktop
Install pyGAEB with the MCP extra:
pip install "pyGAEB[mcp]"
Claude Desktop reads its MCP servers from one file. Open it in any editor (on a Mac: ~/Library/Application Support/Claude/claude_desktop_config.json; on Windows: %APPDATA%\Claude\claude_desktop_config.json) and add the server:
{
"mcpServers": {
"pygaeb": {
"command": "pygaeb-mcp",
"args": ["--root", "/Users/you/tenders"],
"env": {
"PYGAEB_XSD_DIR": "/Users/you/gaeb-xsd"
}
}
}
}
Three things that cost us time, so they do not cost you any:
--rootis the only folder the server may read. Put the files you want to ask about there. A bare file name liketender.X83is looked up under the root, so you never type absolute paths in the chat.envbelongs inside the server entry, next tocommandandargs. We first put it at the top level of the file, where it is silently ignored.PYGAEB_XSD_DIRpoints at the official GAEB DA XML schemas and turns on schema validation for every file you open; without it you get one info note per file saying validation was skipped. (Since 1.18 there is also a--xsd-dirflag.)commandmay need the full path. The app does not run your shell profile, so ifpygaeb-mcplives in a virtual environment, write/path/to/venv/bin/pygaeb-mcp.
Then fully quit Claude Desktop (⌘Q on a Mac, not just the window) and reopen it. Under Settings → Developer the server shows as running, and the tools panel in a new chat lists the ten read tools.

For Claude Code, the same thing is one line:
claude mcp add pygaeb -e PYGAEB_XSD_DIR=/Users/you/gaeb-xsd -- pygaeb-mcp --root /Users/you/tenders
What you can ask Claude about a GAEB bid
The folder held a small bid for a school renovation — windows and exterior doors, nine positions, three categories — and the BVBS sample bill of quantities that every GAEB developer knows, 28 positions of earthworks, masonry, concrete and electrical work. Both are sample files, and one of them is deliberately odd; that turned out to be useful.
Every answer below is quoted from the session as Claude wrote it, trimmed for length. Nothing was edited for accuracy.
"Open the school bid and summarise it"
This is a GAEB DA XML 3.3 bid (X84) for Sanierung Grundschule Lindenhof (project no. 2026-042). The client is Stadt Musterstadt, Amt für Gebäudemanagement, and the scope is replacing the windows and exterior doors in Bauteil A and B. The opening date is 14 August 2026; no time or submission location is given.
The bid total is €581,000.00. The file doesn't state a total, so this figure is calculated as quantity × unit price. I wouldn't rely on it, for two reasons: 5 of the 9 items have no price, including the 22 main windows, which should be the core of this job. And the prices that are there look wrong. The aluminium exterior sills at €12,000 per metre make up about two thirds of the total. That price is roughly a hundred times too high and looks like a decimal or unit error.

That last paragraph is the point of the whole exercise. The tool returned a handle, a summary and nine rows; the judgement — a windowsill cannot cost €12,000 a metre, and a bid that leaves its 22 windows unpriced is not a bid yet — is what an estimator would have said after ten minutes with the file. Claude said it after one.
"List only items with a total above 5,000 EUR, largest first"
Four items have a total above €5,000.
OZ Item Qty Unit price Total Share 02.0050 Exterior sill, aluminium, 180 mm projection 32.5 m 12,000.00 390,000.00 67.1 % 03.0020 Side entrance door, aluminium, 1010×2180 3 St 28,000.00 84,000.00 14.5 % 03.0010 Main entrance door, aluminium, 1250×2180 2 St 28,000.00 56,000.00 9.6 % 02.0030 Fixed glazing 760×1230 6 St 8,500.00 51,000.00 8.8 % The other five items aren't below €5,000; they have no price at all, so the filter can't tell how much they would add.

One tool call, one table. The last sentence is the one to notice: "no price" and "below the threshold" are different things, and the server returns null rather than zero for an unpriced position so that the assistant can tell them apart.
"Which positions mention 'Außentür'?"
Three positions match "Außentür". In every case the word comes from their category name, 03 Außentüren Aluminium (aluminium exterior doors), not from the item's own text. None of the item descriptions uses the word itself, and none of these items has a long text to search.

Category labels are where a lot of the meaning in a German bill of quantities lives — the positions under Außentüren are called Haustürelement and Nebeneingangstür. The search tool looks at the category path as well as the item text and says which one matched.
"In the school bid, which category contributes most to the computed total, and how many of its items are unpriced?"
This one needs three tool calls and some arithmetic.
Category 02, Fensterelemente Kunststoff (PVC windows), contributes the most: €441,000.00, or 75.9 % of the €581,000.00 computed total. 3 of its 5 items are unpriced.
So the category's lead rests almost entirely on the €12,000-per-metre exterior sill price, which looks like an error. Its 22 windows, the actual core of the job, carry no price at all. If the sill price is corrected and the windows are priced, both the total and each category's share could change substantially.
"Open the BVBS sample and list its validation issues"
It has 7 validation issues: 2 errors, 3 warnings, 2 info.
Errors (2). The position number 001.001.0010 appears 3 times in lot 1. The position number 999.999.9999 appears 3 times in lot 1. Duplicate position numbers are the serious problem here. Tools, and bid comparisons, identify an item by its position number. When one number appears three times, prices can be matched to the wrong entry, overwritten, or counted more than once.
Warnings (3). These are all XSD schema-order problems in the file header. Info. The file was written by pyGAEB 1.14.1. Re-exporting it with 1.18.0 would fix the header and schema-order warnings.
That last note is the server telling on itself: the sample copy had been written by an old pyGAEB whose output did not yet pass the official schema. The current writer does, and the assistant was told so rather than left to worry about header warnings. If you only need this check on a file someone sent you, the free GAEB-Check shows the same duplicates and schema findings in the browser, no setup.
"What delivery deadline and glazing U-value does the school bid require for the windows?"
The answer we were hoping for was "it isn't in the file" — the file has no long texts, no dates apart from the opening, and no U-value anywhere. An assistant that invents one here would be dangerous.
The school bid doesn't specify either one: there's no delivery deadline and no glazing U-value anywhere in the file. None of the 9 positions has a long text, and the short texts give only the window type and size. Construction start, construction end, evaluation end and submission location are all empty. The only date in the file is the bid opening, 14 August 2026.
These requirements may be in the tender documents that came with the bill of quantities, such as the preliminary remarks (Vorbemerkungen), technical specifications or contract terms, rather than in this bid file.

This is where the bid file stops and the tender package begins. Deadlines, eligibility and exclusion criteria, contract clauses and the technical specification live in the PDFs that come with the bill of quantities — and reading those next to the positions, with a citation for every fact, is what the DatumOS dossier is built to do.
Every figure Claude stated in the session could be traced to a tool result. That is not luck; it is what the server is built for. It returns small, typed answers — counts, pages, one item at a time — so that the model has nothing to fill in.
What the test found in pyGAEB (fixed in 1.18)
We ran the same questions before and after fixing what we saw, and the "before" was humbling. Sixteen findings, most of them one root cause — in the same parser DatumOS runs on, so every one of them mattered twice.
pyGAEB keeps a position's number in two parts: the leaf RNoPart (0010) and the category chain above it. Every tool that identified a position used the leaf alone. In a real bill of quantities the leaf recurs in every category, so:
- the document comparison paired a window position with a trench excavation because both were
0020; - the bid ranking collapsed 28 positions into 7 keys;
- validation said "Item 0030: missing short text" when five items carried that number;
- "get item 0010" silently returned the first one.
Around it, smaller things: a bid that stated no position totals was reported as "stated total €0" next to a six-figure computed total; a "Default lot" that the file never contained showed up in every structure listing; the opening date was parsed but never shown; a search for Außentür found nothing because category labels were not searched.
All of that is pyGAEB 1.18.0. A second round of harder, multi-step questions found six more — a markup position whose 48 % rate was shown where a price would be, a repeated position number whose second copy could not be reached, no way to tell seventeen identical files apart without opening all of them — and those are 1.18.1. Both are on PyPI; the changelog has the full list.
The lesson we would pass on to anyone building an MCP server: unit tests told us the tools worked. Only a model asking real questions told us what the tools were not saying.
Where this fits
The MCP server is pyGAEB reaching the people who do not write Python — MIT-licensed, on GitHub, running on your machine with your files never leaving it. If you do write Python, the library itself gives you the same parser without a model in between. If you only want a quick look at one file, there are four ways to open a GAEB file without special software, and the free GAEB-Check is the one that needs nothing installed. When a team needs the same questions answered every week, with pricing, a dossier and a Preisspiegel that stay in one place, that is what DatumOS is for — if you want to try it on your own tenders, request a pilot; the first companies are in the programme now.
If you try the setup and something does not work, the MCP server guide has the troubleshooting list — and a GitHub issue with the question you asked is the most useful bug report we can get.
Was this article helpful?
No cookies, no tracking — one vote per reader per day.
Comments
Comments are reviewed before they appear.
Loading comments…